package com.tsfyun.scm.service.impl.order;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.text.StrSpliter;
import cn.hutool.core.util.StrUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.base.Stopwatch;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.tsfyun.common.base.dto.*;
import com.tsfyun.common.base.enums.*;
import com.tsfyun.common.base.enums.domain.*;
import com.tsfyun.common.base.enums.finance.TransactionCategoryEnum;
import com.tsfyun.common.base.enums.finance.TransactionTypeEnum;
import com.tsfyun.common.base.enums.risk.RiskApprovalDocTypeEnum;
import com.tsfyun.common.base.exception.ServiceException;
import com.tsfyun.common.base.help.excel.ExcelUtil;
import com.tsfyun.common.base.security.SecurityUtil;
import com.tsfyun.common.base.support.DomainStatus;
import com.tsfyun.common.base.util.*;
import com.tsfyun.common.base.validator.ValidatorUtils;
import com.tsfyun.common.base.validator.group.AddGroup;
import com.tsfyun.common.base.validator.group.UpdateGroup;
import com.tsfyun.scm.base.DataCalling;
import com.tsfyun.scm.dto.order.*;
import com.tsfyun.scm.dto.support.TaskNoticeContentDTO;
import com.tsfyun.scm.entity.base.Currency;
import com.tsfyun.scm.entity.customer.*;
import com.tsfyun.scm.entity.customs.Declaration;
import com.tsfyun.scm.entity.finance.ImpSalesContract;
import com.tsfyun.scm.entity.order.*;
import com.tsfyun.scm.entity.risk.RiskApproval;
import com.tsfyun.scm.entity.user.Person;
import com.tsfyun.scm.entity.wms.ReceivingNote;
import com.tsfyun.scm.entity.wms.ReceivingNoteMember;
import com.tsfyun.scm.excel.AuxiliaryInspectionExcel;
import com.tsfyun.scm.excel.OrderMemberExcel;
import com.tsfyun.scm.mapper.order.ImpOrderMapper;
import com.tsfyun.scm.service.base.ISystemCacheService;
import com.tsfyun.scm.service.common.ICommonService;
import com.tsfyun.scm.service.customer.*;
import com.tsfyun.scm.service.customs.IDeclarationService;
import com.tsfyun.scm.service.file.IExportFileService;
import com.tsfyun.scm.service.file.IUploadFileService;
import com.tsfyun.scm.service.finance.IImpSalesContractService;
import com.tsfyun.scm.service.finance.IPaymentAccountMemberService;
import com.tsfyun.scm.service.finance.ITransactionFlowService;
import com.tsfyun.scm.service.finance.IWriteOffService;
import com.tsfyun.scm.service.logistics.IDeliveryWaybillService;
import com.tsfyun.scm.service.order.*;
import com.tsfyun.common.base.extension.ServiceImpl;
import com.tsfyun.scm.service.risk.IRiskApprovalService;
import com.tsfyun.scm.service.support.ITaskNoticeContentService;
import com.tsfyun.scm.service.system.ISerialNumberService;
import com.tsfyun.scm.service.system.IStatusHistoryService;
import com.tsfyun.scm.service.system.ISubjectOverseasService;
import com.tsfyun.scm.service.system.ISubjectService;
import com.tsfyun.scm.service.third.IShortMessageService;
import com.tsfyun.scm.service.third.IWxMessageService;
import com.tsfyun.scm.service.user.IPersonService;
import com.tsfyun.scm.service.wms.IDeliveryNoteService;
import com.tsfyun.scm.service.wms.IReceivingNoteMemberService;
import com.tsfyun.scm.service.wms.IReceivingNoteService;
import com.tsfyun.scm.stream.send.ScmProcessor;
import com.tsfyun.scm.system.vo.CountryVO;
import com.tsfyun.scm.util.PermissionUtil;
import com.tsfyun.scm.util.TsfWeekendSqls;
import com.tsfyun.scm.vo.order.*;
import com.tsfyun.scm.vo.system.SubjectOverseasVO;
import com.tsfyun.scm.vo.system.SubjectVO;
import com.tsfyun.scm.vo.user.SimplePersonInfo;
import jxl.format.Alignment;
import jxl.format.VerticalAlignment;
import jxl.write.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.session.RowBounds;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.integration.redis.util.RedisLockRegistry;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;
import tk.mybatis.mapper.entity.Example;

import java.io.File;
import java.io.InputStream;
import java.lang.Boolean;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.function.Function;
import java.util.stream.Collectors;


/**
 * <p>
 * 进口订单 服务实现类
 * </p>
 *

 * @since 2020-04-08
 */
@RefreshScope
@Slf4j
@Service
public class ImpOrderServiceImpl extends ServiceImpl<ImpOrder> implements IImpOrderService {

    @Autowired
    private ICustomerService customerService;
    @Autowired
    private IImpOrderCheckWrapService impOrderCheckWrapService;
    @Autowired
    private IUploadFileService uploadFileService;
    @Autowired
    private IImpOrderMemberService impOrderMemberService;
    @Autowired
    private IImpOrderMemberHistoryService impOrderMemberHistoryService;
    @Autowired
    private IImpOrderLogisticsService impOrderLogisticsService;
    @Autowired
    private IStatusHistoryService statusHistoryService;
    @Autowired
    private ImpOrderMapper impOrderMapper;
    @Autowired
    private IPersonService personService;
    @Autowired
    private IImpQuoteService impQuoteService;
    @Autowired
    private IImpOrderCostService impOrderCostService;
    @Autowired
    private ISupplierService supplierService;
    @Autowired
    private IAgreementService agreementService;
    @Autowired
    private IImpOrderPriceService impOrderPriceService;
    @Autowired
    private ICommonService commonService;
    @Autowired
    private ITaskNoticeContentService taskNoticeContentService;
    @Autowired
    private IReceivingNoteService receivingNoteService;
    @Autowired
    private IReceivingNoteMemberService receivingNoteMemberService;
    @Autowired
    private Snowflake snowflake;
    @Autowired
    private IOrderMemberReceivingNoService orderMemberReceivingNoService;
    @Autowired
    private IOrderReceivingNoteMemberService orderReceivingNoteMemberService;
    @Autowired
    private IRiskApprovalService riskApprovalService;
    @Autowired
    private IDeclarationService declarationService;
    @Autowired
    private RedisLockRegistry redisLockRegistry;
    @Value("${redis.lock.time:5}")
    private Integer lockTime;
    @Autowired
    private ITransactionFlowService transactionFlowService;
    @Value("${orderMember.upload.excel.maxmum:50}")
    private int uploadMaxmum;
    @Autowired
    private ScmProcessor processor;
    @Autowired
    private IDeliveryWaybillService deliveryWaybillService;
    @Autowired
    private IPaymentAccountMemberService paymentAccountMemberService;
    @Autowired
    private ISubjectService subjectService;
    @Autowired
    private ISubjectOverseasService subjectOverseasService;
    @Autowired
    private IShortMessageService shortMessageService;
    @Autowired
    private IWxMessageService wxMessageService;
    @Autowired
    private ISystemCacheService systemCacheService;
    @Autowired
    private ISerialNumberService serialNumberService;
    @Autowired
    private IWriteOffService writeOffService;
    @Autowired
    private ICostChangeRecordService costChangeRecordService;
    @Autowired
    private IImpSalesContractService impSalesContractService;
    @Autowired
    private IDeliveryNoteService deliveryNoteService;
    @Value("${file.directory}")
    private String filePath;
    @Autowired
    private IExportFileService exportFileService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long clienAdd(ImpOrderPlusDTO orderDto) {
        //获取默认主体（外贸合同买方）
        SubjectVO subject = subjectService.findByCode();
        orderDto.getOrder().setSubjectId(subject.getId());
        //获取境外公司（外贸合同卖方）
        SubjectOverseasVO subjectOverseas = subjectOverseasService.defOverseas();
        orderDto.getOrder().setSubjectOverseasId(subjectOverseas.getId());
        //设置客户
        orderDto.getOrder().setCustomerId(SecurityUtil.getCurrentCustomerId());
        return add(orderDto);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void clienEdit(ImpOrderPlusDTO orderDto) {
        //获取默认主体（外贸合同买方）
        SubjectVO subject = subjectService.findByCode();
        orderDto.getOrder().setSubjectId(subject.getId());
        //获取境外公司（外贸合同卖方）
        SubjectOverseasVO subjectOverseas = subjectOverseasService.defOverseas();
        orderDto.getOrder().setSubjectOverseasId(subjectOverseas.getId());
        //设置客户
        orderDto.getOrder().setCustomerId(SecurityUtil.getCurrentCustomerId());
        edit(orderDto);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Long add(ImpOrderPlusDTO orderDto) {
        Stopwatch stopwatch = Stopwatch.createStarted();
        Boolean isSubmit = Objects.equals(Boolean.TRUE,orderDto.getSubmitAudit());
        //验证订单数据
        ValidatorUtils.validateEntityWithRow(orderDto,isSubmit ? UpdateGroup.class : AddGroup.class);

        ImpOrder impOrder = new ImpOrder();
        //赋值订单主单
        ImpOrderDTO dto = orderDto.getOrder();
        Customer customer = null;
        if(Objects.isNull(dto.getCustomerId())){
            customer = customerService.findByNameWithRight(dto.getCustomerName());
        }else{
            customer = customerService.getById(dto.getCustomerId());
        }
        if(Objects.isNull(customer)){
            throw new ServiceException("客户不存在");
        }
        impOrder.setCustomerId(customer.getId());
        orderDto.getOrder().setCustomerName(customer.getName());
        // 填充订单主单信息
        fullOrderMain(impOrder,orderDto.getOrder());
        ImpOrderStatusEnum statusEnum = null;//状态
        //提交审核
        if(isSubmit){
            statusEnum = ImpOrderStatusEnum.WAIT_PRICE;
            //待审价
            impOrder.setStatusId(statusEnum.getCode());
        }else{
            statusEnum = ImpOrderStatusEnum.TEMP_SAVED;
            //临时保存
            impOrder.setStatusId(statusEnum.getCode());
        }
        impOrder.setPayVal(BigDecimal.ZERO);//已付汇金额
        impOrder.setIsImp(Boolean.FALSE);//生成报关单确定进口


        //物流数据
        ImpOrderLogistics impOrderLogistics = new ImpOrderLogistics();
        ImpOrderLogisticsDTO paramLogisticsDTO = orderDto.getLogistiscs();
        //校验赋值香港物流
        impOrderCheckWrapService.checkWrapOverseasLogistics(impOrderLogistics,paramLogisticsDTO,isSubmit);
        //校验赋值国内物流
        impOrderCheckWrapService.checkWrapDomesticLogistics(impOrderLogistics,paramLogisticsDTO,isSubmit);
        //订单明细数据
        List<ImpOrderMemberDTO> paramMembers = orderDto.getMembers();
        //校验赋值订单明细
        ImpOrderMemberSaveDTO impOrderMemberSaveDTO = impOrderCheckWrapService.checkWrapOrderMember(impOrder,paramMembers,isSubmit);
        try {
            if(Objects.equals(TransactionModeEnum.of(impOrder.getTransactionMode()),TransactionModeEnum.FOB)){
                List<String> stringList = DataCalling.getInstance().impFOBRateStr();
                impOrder.setTransCosts(stringList.get(0));//运费
                impOrder.setInsuranceCosts(stringList.get(1));//保费
                impOrder.setMiscCosts(stringList.get(2));//杂费
            }
            super.saveNonNull(impOrder);

            //保存物流信息
            impOrderLogistics.setId(impOrder.getId());
            impOrderLogistics.setImpOrderId(impOrder.getId());
            impOrderLogisticsService.saveNonNull(impOrderLogistics);

            //新增订单明细
            Integer newSize = impOrderMemberService.saveMembers(impOrder,impOrderMemberSaveDTO,isSubmit);

            //关联文件信息
            uploadFileService.relateFile(impOrder.getId().toString(),orderDto.getFile());

            //记录历史状态
            statusHistoryService.saveHistory(DomainOprationEnum.ORDER_ADD,
                    impOrder.getId().toString(),ImpOrder.class.getName(),
                    statusEnum.getCode(),statusEnum.getName(),
                    Objects.equals(ImpOrderStatusEnum.TEMP_SAVED,statusEnum)?"临时保存":"提交审核"
            );
            // 计算审价
            if(Objects.equals(ImpOrderStatusEnum.WAIT_PRICE,statusEnum)){
                impOrderPriceService.calculatingPrice(impOrder);
            }
            if(newSize>0){
                //发送任务通知 通知关务归类
                TaskNoticeContentDTO taskNoticeContentDTO = new TaskNoticeContentDTO();
                taskNoticeContentDTO.setDocumentType(DomainTypeEnum.MATERIEL.getCode());
                taskNoticeContentDTO.setDocumentId("-1");
                taskNoticeContentDTO.setCustomerId(customer.getId());
                taskNoticeContentDTO.setOperationCode(DomainOprationEnum.MATERIEL_CLASSIFY.getCode());
                taskNoticeContentDTO.setContent(String.format("客户【%s】有新物料需要您归类，请立即处理。",customer.getName()));
                Map<String,Object> queryParamsMap = new LinkedHashMap<String,Object>(){{
                    put("statusId",MaterielStatusEnum.WAIT_CLASSIFY.getCode());
                }};
                queryParamsMap.put("customerName",customer.getName());
                taskNoticeContentDTO.setQueryParamsMap(queryParamsMap);
                taskNoticeContentDTO.setIsExeRemove(Boolean.TRUE);
                taskNoticeContentService.add(taskNoticeContentDTO);
            }
        }catch (DuplicateKeyException e) {
            if(StringUtils.isNotEmpty(e.getMessage()) && e.getMessage().contains("UK_imp_order_doc_no")) {
                throw new ServiceException("订单编号已经存在请修改");
            }else {
                throw new ServiceException("保存失败，请检查数据是否填写正确");
            }
        }

        log.info("客户【{}】新增订单数据【{}】成功，耗时【{}】秒",customer.getName(),isSubmit ? "提交审核" : "临时保存",stopwatch.elapsed(TimeUnit.SECONDS));
        return impOrder.getId();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void edit(ImpOrderPlusDTO orderDto) {
        Stopwatch stopwatch = Stopwatch.createStarted();
        Boolean isSubmit = Objects.equals(Boolean.TRUE,orderDto.getSubmitAudit());
        //验证订单数据
        ValidatorUtils.validateEntityWithRow(orderDto,isSubmit ? UpdateGroup.class : AddGroup.class);
        ImpOrderDTO dto = orderDto.getOrder();
        ImpOrder impOrder = super.getById(dto.getId());
        TsfPreconditions.checkArgument(Objects.nonNull(impOrder),new ServiceException("订单不存在"));
        //原始单据状态
        ImpOrderStatusEnum historyStatus = ImpOrderStatusEnum.of(impOrder.getStatusId());
        //验证状态是否可以执行操作
        DomainOprationEnum oprationEnum = DomainOprationEnum.ORDER_EDIT;
        DomainStatus.getInstance().check(oprationEnum, impOrder.getStatusId());
        Customer customer;
        if(Objects.isNull(dto.getCustomerId())){
            customer = customerService.findByNameWithRight(dto.getCustomerName());
        }else{
            customer = customerService.getById(dto.getCustomerId());
        }
        if(Objects.isNull(customer)){
            throw new ServiceException("客户不存在");
        }
        impOrder.setCustomerId(customer.getId());
        orderDto.getOrder().setCustomerName(customer.getName());
        // 填充订单主单信息
        fullOrderMain(impOrder,orderDto.getOrder());
        //提交->待审计，暂存->临时保存
        ImpOrderStatusEnum statusEnum = isSubmit ? ImpOrderStatusEnum.WAIT_PRICE : ImpOrderStatusEnum.TEMP_SAVED;//状态
        impOrder.setStatusId(statusEnum.getCode());
        //物流数据
        ImpOrderLogistics impOrderLogistics = impOrderLogisticsService.getById(impOrder.getId());
        ImpOrderLogisticsDTO paramLogisticsDTO = orderDto.getLogistiscs();
        //校验赋值香港物流
        impOrderCheckWrapService.checkWrapOverseasLogistics(impOrderLogistics,paramLogisticsDTO,isSubmit);
        //校验赋值国内物流
        impOrderCheckWrapService.checkWrapDomesticLogistics(impOrderLogistics,paramLogisticsDTO,isSubmit);
        //订单明细数据
        List<ImpOrderMemberDTO> paramMembers = orderDto.getMembers();
        //校验赋值订单明细
        ImpOrderMemberSaveDTO impOrderMemberSaveDTO = impOrderCheckWrapService.checkWrapOrderMember(impOrder,paramMembers,isSubmit);
        try {
            super.updateById(impOrder);

            //保存物流信息
            impOrderLogistics.setImpOrderId(impOrder.getId());
            impOrderLogisticsService.updateById(impOrderLogistics);

            //修改订单明细
            Integer newSize = impOrderMemberService.saveMembers(impOrder,impOrderMemberSaveDTO,isSubmit);

            //记录历史状态
            statusHistoryService.saveHistory(oprationEnum,
                    impOrder.getId().toString(),ImpOrder.class.getName(),
                    historyStatus.getCode(),historyStatus.getName(),
                    statusEnum.getCode(),statusEnum.getName(),
                    Objects.equals(ImpOrderStatusEnum.TEMP_SAVED,statusEnum)?"临时保存":"提交审核"
            );
            //验证是否需要审价
            if(Objects.equals(ImpOrderStatusEnum.WAIT_PRICE,statusEnum)){
                impOrderPriceService.calculatingPrice(impOrder);
            }
            //清除修改任务提示
            taskNoticeContentService.deleteTaskNotice(DomainTypeEnum.IMPORDER.getCode(), impOrder.getId(), DomainOprationEnum.ORDER_EDIT.getCode());
            if(newSize>0){
                //发送任务通知 通知关务归类
                TaskNoticeContentDTO taskNoticeContentDTO = new TaskNoticeContentDTO();
                taskNoticeContentDTO.setDocumentType(DomainTypeEnum.MATERIEL.getCode());
                taskNoticeContentDTO.setDocumentId("-1");
                taskNoticeContentDTO.setCustomerId(customer.getId());
                taskNoticeContentDTO.setOperationCode(DomainOprationEnum.MATERIEL_CLASSIFY.getCode());
                taskNoticeContentDTO.setContent(String.format("客户【%s】有新物料需要您归类，请立即处理。",customer.getName()));
                Map<String,Object> queryParamsMap = new LinkedHashMap<String,Object>(){{
                    put("statusId",MaterielStatusEnum.WAIT_CLASSIFY.getCode());
                }};
                queryParamsMap.put("customerName",customer.getName());
                taskNoticeContentDTO.setQueryParamsMap(queryParamsMap);
                taskNoticeContentDTO.setIsExeRemove(Boolean.TRUE);
                taskNoticeContentService.add(taskNoticeContentDTO);
            }
        }catch (DuplicateKeyException e) {
            if(e.getMessage().contains("UK_imp_order_doc_no")) {
                throw new ServiceException("订单编号已经存在请修改");
            }else {
                log.error("保存失败：",e);
                throw new ServiceException("保存失败，请检查数据是否填写正确");
            }
        }
        log.info("客户【{}】新增订单数据【{}】成功，耗时【{}】秒",customer.getName(),isSubmit ? "提交审核" : "临时保存",stopwatch.elapsed(TimeUnit.SECONDS));
    }

    //赋值订单主单
    private void fullOrderMain(ImpOrder impOrder,ImpOrderDTO dto){
        impOrder.setDocNo(dto.getDocNo());
        impOrder.setClientNo(StringUtils.isNotEmpty(dto.getClientNo()) ? dto.getClientNo() : dto.getDocNo());
        //客户单号不允许存在重复的
        Example clientExample = Example.builder(ImpOrder.class).where(TsfWeekendSqls.<ImpOrder>custom()
                .andEqualTo(false,ImpOrder::getClientNo,impOrder.getClientNo())).build();
        List<ImpOrder> clientOrders = impOrderMapper.selectByExampleAndRowBounds(clientExample,new RowBounds(0,2));
        if(Objects.isNull(dto.getId())) {
            //新增
            TsfPreconditions.checkArgument(CollUtil.isEmpty(clientOrders), new ServiceException(StrUtil.format("客户单号【{}】已经存在", impOrder.getClientNo())));
        } else {
            ValidatorUtils.isTrue(clientOrders.stream().filter(r->!Objects.equals(r.getId().longValue(),impOrder.getId())).count() <= 0,()->new ServiceException(StrUtil.format("客户单号【{}】已经存在", impOrder.getClientNo())));
        }
        Supplier supplier = supplierService.findByCustomerNameAndSupplierName(dto.getCustomerName(),dto.getSupplierName());
        TsfPreconditions.checkArgument(Objects.nonNull(supplier),new ServiceException("境外供应商不存在"));
        impOrder.setSupplierId(supplier.getId());
        //订单日期
        impOrder.setOrderDate(LocalDateTimeUtils.convertLocalDate());
        //业务类型
        impOrder.setBusinessType(dto.getBusinessType());
        //校验赋值币制信息
        Currency currency = impOrderCheckWrapService.checkWrapCurrency(dto.getCurrencyName());
        impOrder.setCurrencyId(currency.getId());
        impOrder.setCurrencyName(currency.getName());
        impOrder.setTransactionMode(dto.getTransactionMode());//成交方式
        //(外贸合同买方)
        impOrder.setSubjectId(dto.getSubjectId());
        //(外贸合同卖方)
        impOrder.setSubjectOverseasId(dto.getSubjectOverseasId());
        impOrder.setMemo(dto.getMemo());//备注

        //获取报价
        ImpQuote impQuote = impQuoteService.getById(dto.getImpQuoteId());
        TsfPreconditions.checkArgument(Objects.nonNull(impQuote),new ServiceException("客户报价不存在"));
        impOrder.setImpQuoteId(impQuote.getId());
        //根据报价取协议
        Agreement agreement = agreementService.getById(impQuote.getAgreementId());
        TsfPreconditions.checkArgument(Objects.nonNull(agreement),new ServiceException("客户协议不存在"));
        TsfPreconditions.checkArgument(Objects.equals(impOrder.getCustomerId(),agreement.getCustomerId()),new ServiceException("客户协议不存在"));
        //报关类型
        impOrder.setDeclareType(agreement.getDeclareType());
        //商务确定后再写入
        impOrder.setCustomsRate(BigDecimal.ZERO);
        impOrder.setUsdRate(BigDecimal.ZERO);
        impOrder.setImpRate(BigDecimal.ZERO);
    }

    @Override
    public PageInfo<ImpOrderVO> list(ImpOrderQTO qto) {
        //如果传了动态日期字段，检查是否包含该字段以防数据库报错
        if(StringUtils.isNotEmpty(qto.getQueryDate())) {
            TsfPreconditions.checkArgument(ClassUtil.containsField(ImpOrder.class,qto.getQueryDate()),new ServiceException("日期查询类型参数错误"));
        }
        PageHelper.startPage(qto.getPage(),qto.getLimit());
        Map<String,Object> params = beanMapper.map(qto,Map.class);
        List<ImpOrderVO> list = impOrderMapper.list(params);
        //取客户对应的销售和商务人员名称
        if(CollUtil.isNotEmpty(list)) {
            Set<Long> personSet = Sets.newHashSet(list.stream().map(ImpOrderVO::getSalePersonId).collect(Collectors.toSet()));
            personSet.addAll(list.stream().map(ImpOrderVO::getBusPersonId).collect(Collectors.toSet()));
            Map<Long,SimplePersonInfo> personMap = personService.findByIds(personSet);
            if(CollectionUtil.isNotEmpty(personMap)) {
                list.stream().forEach(r->{
                    SimplePersonInfo simpleSalePersonInfo = personMap.get(r.getSalePersonId());
                    SimplePersonInfo simpleBusPersonInfo = personMap.get(r.getBusPersonId());
                    r.setSalePersonName(Objects.nonNull(simpleSalePersonInfo) ? simpleSalePersonInfo.getName() : null);
                    r.setBusPersonName(Objects.nonNull(simpleBusPersonInfo) ? simpleBusPersonInfo.getName() : null);
                });
            }
        }
        return new PageInfo<>(list);
    }

    @Override
    public PageInfo<ClientImpOrderVO> clientList(ClientImpOrderQTO qto) {
        qto.setCustomerId(SecurityUtil.getCurrentCustomerId());
        PageHelper.startPage(qto.getPage(),qto.getLimit());
        List<ClientImpOrderVO> list = impOrderMapper.clientList(qto);
        if(CollectionUtil.isNotEmpty(list)){
            //解析前1条明细
            list.stream().forEach(clientImpOrderVO -> {
                List<String> memSplits = StrSpliter.split(clientImpOrderVO.getMemDesc(), "|$@", 0, true, false);
                if(CollUtil.isNotEmpty(memSplits) && memSplits.size() == 5) {
                    ImpOrderMemberSimpleVO member = new ImpOrderMemberSimpleVO(Objects.nonNull(memSplits.get(0)) ? Long.valueOf(memSplits.get(0)) : null ,memSplits.get(1),memSplits.get(2),memSplits.get(3),memSplits.get(4));
                    clientImpOrderVO.setMember(member);
                }
            });
        }
        return new PageInfo<>(list);
    }

    @Override
    public ImpOrderPlusVO detailPlus(Long id){
        return detailPlus(id,null);
    }

    @Override
    public ImpOrderDetailVO detail(Long id) {
        return detail(id,null);
    }
    @Override
    public ImpOrderDetailVO detail(Long id,String operation) {
        ImpOrderDetailVO order = impOrderMapper.detail(id);
        TsfPreconditions.checkArgument(Objects.nonNull(order),new ServiceException("订单不存在"));
        //验证状态是否可以执行操作
        DomainOprationEnum domainOpration = DomainOprationEnum.of(operation);
        DomainStatus.getInstance().check(domainOpration, order.getStatusId());
        //获取协议报价
        ImpQuote impQuote = impQuoteService.getById(order.getImpQuoteId());
        if(Objects.nonNull(impQuote)){
            order.setImpQuoteDesc(impQuoteService.quoteDescribe(impQuote));
        }
        if(Objects.equals(DomainOprationEnum.ORDER_EDIT,domainOpration) && Objects.equals(ImpOrderStatusEnum.WAIT_EDIT,ImpOrderStatusEnum.of(order.getStatusId()))){
            // 获取意见
            order.setAuditOpinion(statusHistoryService.findInfoByDomainAndNowStatus(order.getId().toString(),ImpOrder.class.getName(),order.getStatusId()));
        }
        return order;
    }

    @Override
    public ImpOrderPlusVO detailPlus(Long id, String operation) {
        ImpOrderDetailVO order = detail(id,operation);
        ImpOrderLogisticsVO logistiscs = impOrderLogisticsService.findById(id);
        List<ImpOrderMemberVO> members = impOrderMemberService.findOrderMaterielMember(id);
        return new ImpOrderPlusVO(order,logistiscs,members);
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void orderPricing(TaskDTO dto){
        commonService.changeDocumentStatus(dto);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void examine(TaskDTO dto) {
        commonService.changeDocumentStatus(dto);
        //修改后单据状态
        ImpOrderStatusEnum nowStatusEnum = ImpOrderStatusEnum.of(dto.getNewStatusCode());
        TaskNoticeContentDTO taskNoticeContentDTO = new TaskNoticeContentDTO();
        switch (nowStatusEnum){
            case WAIT_INSPECTION://审核通过待验货
                ImpOrder impOrderINS = super.getById(dto.getDocumentId());
                //计算订单费用
                impOrderCostService.calculationCost(impOrderINS);
                //任务通知
                taskNoticeContentDTO.setDocumentType(DomainTypeEnum.IMPORDER.getCode());
                taskNoticeContentDTO.setDocumentId(impOrderINS.getId().toString());
                taskNoticeContentDTO.setCustomerId(impOrderINS.getCustomerId());
                taskNoticeContentDTO.setOperationCode(DomainOprationEnum.ORDER_INSPECTION.getCode());
                taskNoticeContentDTO.setContent(String.format("进口订单【%s】已审核通过，请尽快确认验货", impOrderINS.getDocNo()));
                taskNoticeContentDTO.setQueryParamsMap(ImmutableMap.of("docNo",impOrderINS.getDocNo()));
                taskNoticeContentService.add(taskNoticeContentDTO);
                break;
            case WAIT_EDIT://退回修改
                //任务通知
                ImpOrder impOrderEdit = super.getById(dto.getDocumentId());
                taskNoticeContentDTO.setDocumentType(DomainTypeEnum.IMPORDER.getCode());
                taskNoticeContentDTO.setDocumentId(impOrderEdit.getId().toString());
                taskNoticeContentDTO.setCustomerId(impOrderEdit.getCustomerId());
                taskNoticeContentDTO.setOperationCode(DomainOprationEnum.ORDER_EDIT.getCode());
                taskNoticeContentDTO.setContent(String.format("进口订单【%s】被退回：%s", impOrderEdit.getDocNo(),dto.getMemo()));
                taskNoticeContentDTO.setQueryParamsMap(ImmutableMap.of("docNo",impOrderEdit.getDocNo()));
                taskNoticeContentService.add(taskNoticeContentDTO);
                //发送短信通知客户
                LinkedHashMap<String,String> paramsMap = new LinkedHashMap<>();
                paramsMap.put("orderNo",impOrderEdit.getDocNo());
                SmsNoticeMessageDTO smsNoticeMessageDTO = new SmsNoticeMessageDTO();
                smsNoticeMessageDTO.setMessageNodeEnum(MessageNodeEnum.ORDER_BACK);
                Person person = personService.getPhoneByCustomerId(impOrderEdit.getCustomerId());
                smsNoticeMessageDTO.setPhoneNo(Objects.nonNull(person) ? person.getPhone() : "");
                smsNoticeMessageDTO.setParams(paramsMap);
                shortMessageService.sendNoticeMessage(smsNoticeMessageDTO);
                //发送微信通知
                WxNoticeMessageDTO wxNoticeMessageDTO = new WxNoticeMessageDTO();
                wxNoticeMessageDTO.setWxgzhOpenid(Objects.nonNull(person) ? person.getWxgzhOpenid() : "");
                wxNoticeMessageDTO.setWxMessageDefineTemplate(WxMessageDefineTemplate.ORDER_BACK);
                wxNoticeMessageDTO.setIsNavToMiniprogram(Boolean.TRUE);
                wxNoticeMessageDTO.setMiniprogram(new WxMiniProgram("/pages/order/edit?id=" + impOrderEdit.getId()));
                LinkedHashMap<String, WxNoticeAttr> params = new LinkedHashMap<>();
                params.put("first",new WxNoticeAttr("您的订单已退回待修改"));
                params.put("keyword1",new WxNoticeAttr(impOrderEdit.getDocNo()));
                params.put("keyword2",new WxNoticeAttr(dto.getMemo()));
                params.put("remark",new WxNoticeAttr("点击修改","#9C9C9C"));
                wxNoticeMessageDTO.setParams(params);
                wxMessageService.sendWxNotice(wxNoticeMessageDTO);
                break;
            case WAIT_PRICE://退回审价
                ImpOrder impOrderPrice = super.getById(dto.getDocumentId());
                //进入审价流程
                impOrderPriceService.calculatingPrice(impOrderPrice,Boolean.TRUE);
                break;
            default:
                throw new ServiceException("当前状态不允许此操作");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void confirmImp(TaskDTO dto) {
        String lockKey = DistributedLockEnum.IMP_ORDER_CONFIRM_IMP.getCode() + ":" + dto.getDocumentId();
        Lock lock = redisLockRegistry.obtain(lockKey);
        boolean isLock;
        try {
            isLock = lock.tryLock(lockTime, TimeUnit.SECONDS);
            if(!isLock) {
                log.error(String.format("未获取到锁，订单：【%s】",dto.getDocumentId()));
                throw new ServiceException("服务拥挤，请稍后再试");
            }
            ImpOrder impOrder = commonService.changeDocumentStatus(dto);
            //修改后单据状态
            ImpOrderStatusEnum nowStatusEnum = ImpOrderStatusEnum.of(dto.getNewStatusCode());
            TaskNoticeContentDTO taskNoticeContentDTO = new TaskNoticeContentDTO();
            switch (nowStatusEnum){
                case WAIT_EDIT://退回修改
                    //解除入库单绑定
                    relieveReceivingNoteBind(impOrder);
                    //任务通知
                    taskNoticeContentDTO.setDocumentType(DomainTypeEnum.IMPORDER.getCode());
                    taskNoticeContentDTO.setDocumentId(impOrder.getId().toString());
                    taskNoticeContentDTO.setCustomerId(impOrder.getCustomerId());
                    taskNoticeContentDTO.setOperationCode(DomainOprationEnum.ORDER_EDIT.getCode());
                    taskNoticeContentDTO.setContent(String.format("进口订单【%s】被退回：%s", impOrder.getDocNo(),dto.getMemo()));
                    taskNoticeContentDTO.setQueryParamsMap(ImmutableMap.of("docNo",impOrder.getDocNo()));
                    taskNoticeContentService.add(taskNoticeContentDTO);
                    break;
                case WAIT_INSPECTION://待验货
                    //解除入库单绑定
                    relieveReceivingNoteBind(impOrder);
                    //任务通知
                    taskNoticeContentDTO.setDocumentType(DomainTypeEnum.IMPORDER.getCode());
                    taskNoticeContentDTO.setDocumentId(impOrder.getId().toString());
                    taskNoticeContentDTO.setCustomerId(impOrder.getCustomerId());
                    taskNoticeContentDTO.setOperationCode(DomainOprationEnum.ORDER_INSPECTION.getCode());
                    taskNoticeContentDTO.setContent(String.format("进口订单【%s】需要您重新验货确认：%s", impOrder.getDocNo(),dto.getMemo()));
                    taskNoticeContentDTO.setQueryParamsMap(ImmutableMap.of("docNo",impOrder.getDocNo()));
                    taskNoticeContentService.add(taskNoticeContentDTO);
                    break;
                case WAIT_FK_EXAMINE://待风控审核
                    RiskApproval ra = new RiskApproval();
                    ra.setDocType(RiskApprovalDocTypeEnum.IMP_ORDER_AMOUNT_INSUFFICIENT_MOMEY.getCode());
                    ra.setDocId(impOrder.getId().toString());
                    ra.setDocNo(impOrder.getDocNo());
                    ra.setCustomerId(impOrder.getCustomerId());
                    ra.setSubmitter(SecurityUtil.getCurrentPersonName());
                    ra.setApprovalReason(dto.getMemo());
                    riskApprovalService.submitRiskApproval(ra);
                    break;
                case WAIT_DECLARE://待报关
                    //验证是否需要风控审批
                    OrderCostInfoVO costInfoVO = impOrderCostService.orderCostInfo(impOrder);
                    if(Objects.equals(costInfoVO.getIsAdopt(),Boolean.FALSE)&&!Objects.equals(costInfoVO.getFkAdopt(),Boolean.TRUE)){
                        throw new ServiceException(StringUtils.null2EmptyWithTrim(costInfoVO.getReason()).concat("需要风控审批"));
                    }
                    //验证订单日期
                    if(!LocalDateTimeUtils.formatShort(impOrder.getOrderDate()).equals(LocalDateTimeUtils.formatNow("yyyy-MM-dd"))){
                        throw new ServiceException("订单日期不是最新日期，为防止汇率变化请退回后重新提交");
                    }
                    //获取未锁定的费用信息写入流水
                    List<ImpOrderCostVO> orderCosts = impOrderCostService.obtainOrderNotLockCosts(impOrder.getId());
                    //锁定系统费用
                    impOrderCostService.impLockCost(impOrder.getId());
                    if(CollectionUtil.isNotEmpty(orderCosts)){
                        BigDecimal amount = BigDecimal.ZERO;
                        List<String> costMemos = Lists.newArrayList();
                        for(ImpOrderCostVO oc : orderCosts){
                            costMemos.add(oc.getExpenseSubjectName()+":"+oc.getReceAmount());
                            amount = amount.add(oc.getReceAmount()).setScale(2,BigDecimal.ROUND_HALF_UP);
                        }
                        TransactionFlowDTO param = new TransactionFlowDTO();
                        param.setCustomerId(impOrder.getCustomerId());
                        param.setTransactionType(TransactionTypeEnum.IMP_ORDER.getCode());
                        param.setTransactionCategory(TransactionCategoryEnum.OUTCOME.getCode());
                        param.setTransactionNo(impOrder.getDocNo());
                        param.setAmount(amount);
                        param.setMemo(String.join(";",costMemos));
                        transactionFlowService.recordTransactionFlow(param);
                    }
                    //根据订单生成报关单
                    Declaration declaration = declarationService.createByImpOrder(impOrder);
                    //根据订单生成国内送货
                    deliveryWaybillService.createByImpOrder(impOrder);
                    //修改订单
                    impOrder.setIsImp(Boolean.TRUE);//确定进口
                    impOrder.setDeclarationNo(declaration.getDocNo());//报关单号
                    super.updateById(impOrder);

                    //通知核销
                    CostWriteOffDTO cwdto = new CostWriteOffDTO();
                    cwdto.setTenant("");
                    cwdto.setCustomerId(impOrder.getCustomerId());
                    processor.sendCostWriteOff(cwdto);

                    //发送微信通知
                    Person person = personService.getPhoneByCustomerId(impOrder.getCustomerId());
                    Supplier supplier = supplierService.getById(impOrder.getSupplierId());
                    WxNoticeMessageDTO wxNoticeMessageDTO = new WxNoticeMessageDTO();
                    wxNoticeMessageDTO.setWxgzhOpenid(Objects.nonNull(person) ? person.getWxgzhOpenid() : "");
                    wxNoticeMessageDTO.setWxMessageDefineTemplate(WxMessageDefineTemplate.ORDER_CONFIRM_IMPORT);
                    wxNoticeMessageDTO.setIsNavToMiniprogram(Boolean.TRUE);
                    wxNoticeMessageDTO.setMiniprogram(new WxMiniProgram("pages/order/info?id=" + impOrder.getId()));
                    LinkedHashMap<String, WxNoticeAttr> params = new LinkedHashMap<>();
                    params.put("first",new WxNoticeAttr("尊敬的客户，您好：您有一个订单已确认进口。"));
                    params.put("keyword1",new WxNoticeAttr(impOrder.getDocNo()));
                    params.put("keyword2",new WxNoticeAttr(Objects.nonNull(supplier) ? supplier.getName() : "","#9C9C9C"));
                    String orderContent = StrUtil.format("订单金额:{}，币制:{}，订单日期:{}。",StringUtils.formatCurrency(impOrder.getTotalPrice())
                            ,impOrder.getCurrencyName(),LocalDateTimeUtils.formatTime(impOrder.getOrderDate(),"yyyy-MM-dd"));
                    params.put("keyword3",new WxNoticeAttr(orderContent,"#9C9C9C"));
                    params.put("remark",new WxNoticeAttr("将为您加急报关，点击查看订单详情"));
                    wxNoticeMessageDTO.setParams(params);
                    wxMessageService.sendWxNotice(wxNoticeMessageDTO);
                    break;
                default:
                    throw new ServiceException("当前状态不允许此操作");
            }
        }catch (InterruptedException e) {
            log.error("进口订单确认进口获取锁异常",e);
            throw new ServiceException("服务拥挤，请稍后再试");
        }finally{
            //释放锁
            lock.unlock();
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void backInspection(Long id, String info) {
        String lockKey = DistributedLockEnum.IMP_ORDER_BACK_INSPECTION.getCode() + ":" + id;
        Lock lock = redisLockRegistry.obtain(lockKey);
        boolean isLock;
        try {
            isLock = lock.tryLock(lockTime, TimeUnit.SECONDS);
            if(!isLock) {
                log.error(String.format("未获取到锁，订单：【%s】",id));
                throw new ServiceException("服务拥挤，请稍后再试");
            }
            ImpOrder impOrder = super.getById(id);
            // 原始单据状态
            ImpOrderStatusEnum historyStatus = ImpOrderStatusEnum.of(impOrder.getStatusId());
            ImpOrderStatusEnum WAIT_DECLARE = ImpOrderStatusEnum.WAIT_DECLARE;
            if(Objects.isNull(impOrder) || !Objects.equals(WAIT_DECLARE,historyStatus)){
                throw new ServiceException(String.format("订单不存在或不处于%s状态",WAIT_DECLARE.getName()));
            }
            // 删除国内送货单信息
            deliveryWaybillService.removeByOrderId(impOrder.getId());
            // 反冲销流水
            List<ImpOrderCostVO> orderCosts = impOrderCostService.orderCostList(impOrder.getId());
            BigDecimal amount = BigDecimal.ZERO;
            List<String> costMemos = Lists.newArrayList();
            // 需要反核销的费用ID
            List<Long> cancelWriteOffCostIds = Lists.newArrayList();
            // 需要解锁的费用ID
            List<Long> cancelLockCostIds = Lists.newArrayList();
            for(ImpOrderCostVO oc : orderCosts){
                // 排除货款和手续费
                if(!Arrays.asList("A0005","A0006").contains(oc.getExpenseSubjectId())){
                    costMemos.add(oc.getExpenseSubjectName()+":"+oc.getReceAmount());
                    amount = amount.add(oc.getReceAmount()).setScale(2,BigDecimal.ROUND_HALF_UP);
                    cancelLockCostIds.add(oc.getId());
                    // 核销金额大于零
                    if(oc.getAcceAmount().compareTo(BigDecimal.ZERO) == 1){
                        cancelWriteOffCostIds.add(oc.getId());
                    }
                }
            }
            TransactionFlowDTO param = new TransactionFlowDTO();
            param.setCustomerId(impOrder.getCustomerId());
            param.setTransactionType(TransactionTypeEnum.IMP_ORDER.getCode());
            param.setTransactionCategory(TransactionCategoryEnum.INCOME.getCode());
            param.setTransactionNo(impOrder.getDocNo());
            param.setAmount(amount);
            param.setMemo("进口退单:"+String.join(";",costMemos));
            transactionFlowService.recordTransactionFlow(param);
            // 解锁费用
            if(CollUtil.isNotEmpty(cancelLockCostIds)){
                impOrderCostService.impUnLockCost(cancelLockCostIds);
            }
            // 反核销
            if(CollUtil.isNotEmpty(cancelWriteOffCostIds)){
                cancelWriteOffCostIds.stream().forEach(costId ->{
                    writeOffService.cancelWriteOffByImpOrderCost(impOrderCostService.getById(costId));
                });
            }
            ImpOrderStatusEnum nowStatusEnum = ImpOrderStatusEnum.WAIT_INSPECTION;
            //修改订单
            impOrder.setStatusId(nowStatusEnum.getCode());// 待验货
            impOrder.setIsImp(Boolean.FALSE);//确定进口
            impOrder.setDeclarationNo("");//报关单号
            super.updateById(impOrder);

            //解除入库单绑定
            relieveReceivingNoteBind(impOrder);

            //记录历史状态
            statusHistoryService.saveHistory(DomainOprationEnum.ORDER_CONFIRMIMP_BACK,
                    impOrder.getId().toString(),ImpOrder.class.getName(),
                    historyStatus.getCode(),historyStatus.getName(),
                    nowStatusEnum.getCode(),nowStatusEnum.getName(),info
            );

            //任务通知
            TaskNoticeContentDTO taskNoticeContentDTO = new TaskNoticeContentDTO();
            taskNoticeContentDTO.setDocumentType(DomainTypeEnum.IMPORDER.getCode());
            taskNoticeContentDTO.setDocumentId(impOrder.getId().toString());
            taskNoticeContentDTO.setCustomerId(impOrder.getCustomerId());
            taskNoticeContentDTO.setOperationCode(DomainOprationEnum.ORDER_INSPECTION.getCode());
            taskNoticeContentDTO.setContent(String.format("进口订单【%s】需要您重新验货确认：%s", impOrder.getDocNo(),info));
            taskNoticeContentDTO.setQueryParamsMap(ImmutableMap.of("docNo",impOrder.getDocNo()));
            taskNoticeContentService.add(taskNoticeContentDTO);

        }catch (InterruptedException e) {
            log.error("退单获取锁异常",e);
            throw new ServiceException("服务拥挤，请稍后再试");
        }finally{
            //释放锁
            lock.unlock();
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void declarationCompleted(Long orderId) {
        TaskDTO taskDTO = new TaskDTO();
        taskDTO.setDocumentId(orderId);
        taskDTO.setDocumentClass(DomainTypeEnum.IMPORDER.getCode());
        taskDTO.setOperation(DomainOprationEnum.ORDER_COMPLETE_DEC.getCode());
        taskDTO.setNewStatusCode(ImpOrderStatusEnum.WAIT_CLEARANCE.getCode());
        taskDTO.setMemo("报关单申报完成");
        //可能流程自动触发
        if(StringUtils.isEmpty(SecurityUtil.getCurrentPersonName())){
            taskDTO.setOperator("系统");
        }
        ImpOrder order = commonService.changeDocumentStatus(taskDTO);
        order.setClearanceDate(LocalDateTime.now());
        super.updateById(order);
    }

    @Override
    public List<ImpOrderSimpleVO> selectByOrderNo(String orderNo) {
        return  impOrderMapper.selectByOrderNo(orderNo);
    }

    @Override
    public ImpOrder findByDocNo(String docNo) {
        ImpOrder query = new ImpOrder();
        query.setDocNo(docNo);
        return impOrderMapper.selectOne(query);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void shareNetWeight(Long id, BigDecimal netWeight) {
        if(netWeight.compareTo(BigDecimal.ZERO)!=1){
            throw new ServiceException("总净重必须大于零");
        }
        ImpOrder order = super.getById(id);
        TsfPreconditions.checkArgument(Objects.nonNull(order),new ServiceException("订单不存在"));
        order.setTotalNetWeight(BigDecimal.ZERO);
        List<ImpOrderMember> members = impOrderMemberService.getByOrderId(id);
        if(CollUtil.isNotEmpty(members)){
            BigDecimal quantity = BigDecimal.ZERO;
            for(ImpOrderMember iom : members){
                quantity = quantity.add(iom.getQuantity());
            }
            List<ImpOrderMember> updates = Lists.newArrayList();
            for(ImpOrderMember iom : members){
                BigDecimal shareVal = netWeight.divide(quantity,8,BigDecimal.ROUND_HALF_UP).multiply(iom.getQuantity()).setScale(4,BigDecimal.ROUND_HALF_UP);
                if(shareVal.compareTo(BigDecimal.valueOf(0.01))<0){
                    shareVal = BigDecimal.valueOf(0.01);
                }
                ImpOrderMember update = new ImpOrderMember();
                update.setId(iom.getId());
                update.setNetWeight(shareVal);
                updates.add(update);
                order.setTotalNetWeight(order.getTotalNetWeight().add(update.getNetWeight()).setScale(4,BigDecimal.ROUND_HALF_UP));
            }
            impOrderMemberService.batchUpdatePartData(updates);
        }
        super.updateById(order);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void shareGrossWeight(Long id, BigDecimal grossWeight) {
        if(grossWeight.compareTo(BigDecimal.ZERO)!=1){
            throw new ServiceException("总毛重必须大于零");
        }
        ImpOrder order = super.getById(id);
        TsfPreconditions.checkArgument(Objects.nonNull(order),new ServiceException("订单不存在"));
        order.setTotalCrossWeight(BigDecimal.ZERO);
        List<ImpOrderMember> members = impOrderMemberService.getByOrderId(id);
        if(CollUtil.isNotEmpty(members)){
            BigDecimal quantity = BigDecimal.ZERO;
            for(ImpOrderMember iom : members){
                quantity = quantity.add(iom.getQuantity());
            }
            List<ImpOrderMember> updates = Lists.newArrayList();
            for(ImpOrderMember iom : members){
                BigDecimal shareVal = grossWeight.divide(quantity,8,BigDecimal.ROUND_HALF_UP).multiply(iom.getQuantity()).setScale(4,BigDecimal.ROUND_HALF_UP);
                if(shareVal.compareTo(BigDecimal.valueOf(0.01))<0){
                    shareVal = BigDecimal.valueOf(0.01);
                }
                ImpOrderMember update = new ImpOrderMember();
                update.setId(iom.getId());
                update.setGrossWeight(shareVal);
                updates.add(update);
                order.setTotalCrossWeight(order.getTotalCrossWeight().add(update.getGrossWeight()).setScale(4,BigDecimal.ROUND_HALF_UP));
            }
            impOrderMemberService.batchUpdatePartData(updates);
        }
        super.updateById(order);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchReceivingNo(Long id, String receivingNo) {
        ImpOrderDetailVO order = impOrderMapper.detail(id);
        TsfPreconditions.checkArgument(Objects.nonNull(order),new ServiceException("订单不存在"));
        //验证状态是否可以执行操作
        DomainStatus.getInstance().check(DomainOprationEnum.ORDER_INSPECTION, order.getStatusId());
        //验证入库单号是否正确
        ReceivingNote receivingNote = receivingNoteService.findByDocNo(receivingNo);
        TsfPreconditions.checkArgument(Objects.nonNull(receivingNote),new ServiceException("入库单号输入错误"));
        TsfPreconditions.checkArgument(Objects.equals(order.getCustomerId(),receivingNote.getCustomerId()),new ServiceException("入库单客户与订单客户不一致"));
        List<ImpOrderMember> members = impOrderMemberService.getByOrderId(id);
        if(CollUtil.isNotEmpty(members)){
            List<OrderMemberReceivingNo> orNos = Lists.newArrayList();
            List<ImpOrderMember> updates = Lists.newArrayList();
            members.stream().forEach(iom ->{
                if(StringUtils.isEmpty(iom.getReceivingNoteNo())){
                    OrderMemberReceivingNo orderMemberReceivingNo = new OrderMemberReceivingNo();
                    orderMemberReceivingNo.setId(snowflake.nextId());
                    orderMemberReceivingNo.setOrderMemberId(iom.getId());
                    orderMemberReceivingNo.setReceivingNo(receivingNo);
                    orderMemberReceivingNo.setQuantity(iom.getQuantity());
                    orNos.add(orderMemberReceivingNo);


                    ImpOrderMember update = new ImpOrderMember();
                    update.setId(iom.getId());
                    update.setReceivingNoteNo(receivingNo);
                    update.setReceivingQuantity(iom.getQuantity());
                    updates.add(update);
                }
            });
            if(CollUtil.isNotEmpty(orNos)){
                //修改订单明细
                impOrderMemberService.batchUpdatePartData(updates);
                //添加绑定辅助表
                orderMemberReceivingNoService.savaBatch(orNos);
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveBindMember(BindMemberDTO dto) {
        ImpOrderMember member = impOrderMemberService.getById(dto.getMemberId());
        TsfPreconditions.checkArgument(Objects.nonNull(member),new ServiceException("订单明细不存在"));
        ImpOrder order = super.getById(member.getImpOrderId());
        //验证状态是否可以执行操作
        DomainStatus.getInstance().check(DomainOprationEnum.ORDER_INSPECTION, order.getStatusId());
        List<ReceivingNoDTO> receivingNoDTOList = dto.getReceivingNos();
        orderMemberReceivingNoService.removeByOrderMemberId(member.getId());
        List<String> receivingNos = Lists.newArrayList();
        member.setReceivingNoteNo("");
        member.setReceivingQuantity(BigDecimal.ZERO);
        List<OrderMemberReceivingNo> orNos = Lists.newArrayList();
        receivingNoDTOList.stream().forEach(rndto ->{
            if(receivingNos.contains(rndto.getReceivingNo())){
                throw new ServiceException(String.format("入库单号【%s】重复",rndto.getReceivingNo()));
            }
            receivingNos.add(rndto.getReceivingNo());

            ReceivingNote receivingNote = receivingNoteService.findByDocNo(rndto.getReceivingNo());
            TsfPreconditions.checkArgument(Objects.nonNull(receivingNote),new ServiceException(String.format("入库单号【%s】不存在",rndto.getReceivingNo())));
            TsfPreconditions.checkArgument(Objects.equals(order.getCustomerId(),receivingNote.getCustomerId()),new ServiceException(String.format("入库单【%s】客户与订单客户不一致",rndto.getReceivingNo())));

            OrderMemberReceivingNo orderMemberReceivingNo = new OrderMemberReceivingNo();
            orderMemberReceivingNo.setId(snowflake.nextId());
            orderMemberReceivingNo.setOrderMemberId(member.getId());
            orderMemberReceivingNo.setReceivingNo(rndto.getReceivingNo());
            orderMemberReceivingNo.setQuantity(rndto.getQuantity());
            orNos.add(orderMemberReceivingNo);

            member.setReceivingQuantity(member.getReceivingQuantity().add(orderMemberReceivingNo.getQuantity()));
        });
        if(member.getReceivingQuantity().compareTo(member.getQuantity())==1){
            throw new ServiceException("入库绑定数量不能大于当前订单明细数量");
        }
        //添加绑定辅助表
        orderMemberReceivingNoService.savaBatch(orNos);
        //修改入库明细
        member.setReceivingNoteNo(String.join(",",receivingNos));
        impOrderMemberService.updateById(member);
    }

    @Override
    public ImpOrderMemberVO obtainSplitMember(Long id) {
        ImpOrderMember member = impOrderMemberService.getById(id);
        TsfPreconditions.checkArgument(Objects.nonNull(member),new ServiceException("订单明细不存在"));
        ImpOrder order = super.getById(member.getImpOrderId());
        //验证状态是否可以执行操作
        DomainStatus.getInstance().check(DomainOprationEnum.ORDER_INSPECTION, order.getStatusId());
        if(member.getReceivingQuantity().compareTo(BigDecimal.ZERO) == 1){
            throw new ServiceException("请先解除入库单绑定");
        }
        return beanMapper.map(member,ImpOrderMemberVO.class);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveSplitMember(OrderInspectionMemberDTO dto) {
        ImpOrder impOrder = super.getById(dto.getOrderId());
        TsfPreconditions.checkArgument(Objects.nonNull(impOrder),new ServiceException("订单不存在"));
        //验证状态是否可以执行操作
        DomainStatus.getInstance().check(DomainOprationEnum.ORDER_INSPECTION, impOrder.getStatusId());
        List<ImpOrderMember> members = impOrderMemberService.getByOrderId(impOrder.getId());
        List<ImpOrderMemberDTO> splitMembers = dto.getMembers();
        List<ImpOrderMemberDTO> paramMembers = new ArrayList<>();
        for(ImpOrderMember member : members){
            if(Objects.equals(member.getId(),splitMembers.get(0).getId())){
                for(ImpOrderMemberDTO plitMember : splitMembers){
                    plitMember.setModel(member.getModel());
                    plitMember.setName(member.getName());
                    plitMember.setBrand(member.getBrand());
                    plitMember.setSpec(member.getSpec());
                    plitMember.setGoodsCode(member.getGoodsCode());
                    plitMember.setUnitName(member.getUnitName());
                    paramMembers.add(plitMember);
                }
            }else{
                paramMembers.add(beanMapper.map(member,ImpOrderMemberDTO.class));
            }
        }
        //校验赋值订单明细
        ImpOrderMemberSaveDTO impOrderMemberSaveDTO = impOrderCheckWrapService.checkWrapOrderMember(impOrder,paramMembers,Boolean.TRUE);
        if(CollUtil.isNotEmpty(impOrderMemberSaveDTO.getDeleteOrderMembers())){
            throw new ServiceException("订单明细数据存在变更请刷新页面重试");
        }
        //修改订单明细
        impOrderMemberService.saveInspectionMembers(impOrder,impOrderMemberSaveDTO);
        //修改订单主单
        super.updateById(impOrder);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveInspectionMemberEdit(OrderInspectionMemberDTO dto) {
        ImpOrder impOrder = super.getById(dto.getOrderId());
        TsfPreconditions.checkArgument(Objects.nonNull(impOrder),new ServiceException("订单不存在"));
        //验证状态是否可以执行操作
        DomainStatus.getInstance().check(DomainOprationEnum.ORDER_INSPECTION, impOrder.getStatusId());
        //订单明细数据
        List<ImpOrderMemberDTO> paramMembers = dto.getMembers();
        //校验赋值订单明细
        ImpOrderMemberSaveDTO impOrderMemberSaveDTO = impOrderCheckWrapService.checkWrapOrderMember(impOrder,paramMembers,Boolean.TRUE);
        if(CollUtil.isNotEmpty(impOrderMemberSaveDTO.getDeleteOrderMembers())){
            throw new ServiceException("订单明细数据存在变更请刷新页面重试");
        }
        //修改订单明细
        Integer newSize = impOrderMemberService.saveInspectionMembers(impOrder,impOrderMemberSaveDTO);
        //修改订单主单
        super.updateById(impOrder);
        Customer customer = customerService.getById(impOrder.getCustomerId());
        if(newSize>0){
            //发送任务通知 通知关务归类
            TaskNoticeContentDTO taskNoticeContentDTO = new TaskNoticeContentDTO();
            taskNoticeContentDTO.setDocumentType(DomainTypeEnum.MATERIEL.getCode());
            taskNoticeContentDTO.setDocumentId("-1");
            taskNoticeContentDTO.setCustomerId(customer.getId());
            taskNoticeContentDTO.setOperationCode(DomainOprationEnum.MATERIEL_CLASSIFY.getCode());
            taskNoticeContentDTO.setContent(String.format("客户【%s】有新物料需要您归类，请立即处理。",customer.getName()));
            Map<String,Object> queryParamsMap = new LinkedHashMap<String,Object>(){{
                put("customerName",customer.getName());
                put("statusId",MaterielStatusEnum.WAIT_CLASSIFY.getCode());
            }};
            taskNoticeContentDTO.setQueryParamsMap(queryParamsMap);
            taskNoticeContentDTO.setIsExeRemove(Boolean.TRUE);
            taskNoticeContentService.add(taskNoticeContentDTO);
        }
    }

    @Override
    public InspectionPlusVO auxiliaryInspection(MultipartFile file,Long orderId) {
        try{
            List<AuxiliaryInspectionExcel> dataList = ExcelUtil.readExcel(file, AuxiliaryInspectionExcel.class, 1);
            if(CollUtil.isEmpty(dataList)){
                throw new ServiceException("请至少导入一行数据");
            }
            dataList.stream().forEach(data ->{
                if(StringUtils.isNotEmpty(data.getQuantity())){
                    data.setQuantity(data.getQuantity().replace("，","").replace(",",""));
                }
                if(StringUtils.isNotEmpty(data.getCarton())){
                    data.setCarton(data.getCarton().replace("，","").replace(",",""));
                }
                if(StringUtils.isNotEmpty(data.getNetWeight())){
                    data.setNetWeight(data.getNetWeight().replace("，","").replace(",",""));
                }
                if(StringUtils.isNotEmpty(data.getGrossWeight())){
                    data.setGrossWeight(data.getGrossWeight().replace("，","").replace(",",""));
                }
            });
            Workbook wb = null;
            if(file.getOriginalFilename().endsWith("xls")) {
                //将文件读入
                POIFSFileSystem fs  =new POIFSFileSystem(file.getInputStream());
                wb = new HSSFWorkbook(fs);
            } else if (file.getOriginalFilename().endsWith("xlsx")) {
                //将文件读入
                InputStream in  = file.getInputStream();
                //创建工作簿
                wb = new XSSFWorkbook(in);
            }
            Sheet sheet = wb.getSheetAt(0);
            List<CellRangeAddress> cellRangeAddressList = ExcelUtil.getCombineCell(sheet);
            cellRangeAddressList = cellRangeAddressList.stream().sorted(Comparator.comparing(CellRangeAddress::getFirstColumn)).collect(Collectors.toList());
            cellRangeAddressList.stream().forEach(cell ->{
                //获取合并单元格的行对象
                AuxiliaryInspectionExcel auxiliaryInspectionExcel = dataList.get(cell.getFirstRow()-1);
                if(cell.getFirstColumn()==0){
                    //序号
                    for(int i = cell.getFirstRow();i<cell.getLastRow();i++){
                        dataList.get(i).setRowNo(auxiliaryInspectionExcel.getRowNo());
                    }
                }else if(cell.getFirstColumn()==4){
                    //箱数
                    for(int i = cell.getFirstRow();i<cell.getLastRow();i++){
                        dataList.get(i).setCarton("0");
                    }
                }else if(cell.getFirstColumn()==5){
                    //净重
                    if(!StringUtils.isBigDecimal(auxiliaryInspectionExcel.getNetWeight())){
                        throw new ServiceException(String.format("箱号【%s】净重必须为数值",auxiliaryInspectionExcel.getRowNo()));
                    }
                    //数量
                    if(!StringUtils.isBigDecimal(auxiliaryInspectionExcel.getQuantity())){
                        throw new ServiceException(String.format("箱号【%s】数量必须为数值",auxiliaryInspectionExcel.getRowNo()));
                    }
                    //总净重
                    BigDecimal netWeight = StringUtils.rounded4(auxiliaryInspectionExcel.getNetWeight());
                    //总数量
                    BigDecimal totalQuantity = StringUtils.rounded4(auxiliaryInspectionExcel.getQuantity());
                    for(int i = cell.getFirstRow();i<cell.getLastRow();i++){
                        //其他数量
                        if(!StringUtils.isBigDecimal(dataList.get(i).getQuantity())){
                            throw new ServiceException(String.format("箱号【%s】数量必须为数值",dataList.get(i).getRowNo()));
                        }
                        totalQuantity = StringUtils.rounded4(totalQuantity.add(StringUtils.rounded4(dataList.get(i).getQuantity())));
                    }

                    shareNetWeight(netWeight,totalQuantity,auxiliaryInspectionExcel);
                    for(int i = cell.getFirstRow();i<cell.getLastRow();i++){
                        shareNetWeight(netWeight,totalQuantity,dataList.get(i));
                    }
                }else if(cell.getFirstColumn()==6){
                    //毛重
                    if(!StringUtils.isBigDecimal(auxiliaryInspectionExcel.getGrossWeight())){
                        throw new ServiceException(String.format("箱号【%s】毛重必须为数值",auxiliaryInspectionExcel.getRowNo()));
                    }
                    //数量
                    if(!StringUtils.isBigDecimal(auxiliaryInspectionExcel.getQuantity())){
                        throw new ServiceException(String.format("箱号【%s】数量必须为数值",auxiliaryInspectionExcel.getRowNo()));
                    }
                    //总净重
                    BigDecimal grossWeight = StringUtils.rounded4(auxiliaryInspectionExcel.getGrossWeight());
                    //总数量
                    BigDecimal totalQuantity = StringUtils.rounded4(auxiliaryInspectionExcel.getQuantity());
                    for(int i = cell.getFirstRow();i<cell.getLastRow();i++){
                        //其他数量
                        if(!StringUtils.isBigDecimal(dataList.get(i).getQuantity())){
                            throw new ServiceException(String.format("箱号【%s】数量必须为数值",dataList.get(i).getRowNo()));
                        }
                        totalQuantity = StringUtils.rounded4(totalQuantity.add(StringUtils.rounded4(dataList.get(i).getQuantity())));
                    }
                    shareGrossWeight(grossWeight,totalQuantity,auxiliaryInspectionExcel);
                    for(int i = cell.getFirstRow();i<cell.getLastRow();i++){
                        shareGrossWeight(grossWeight,totalQuantity,dataList.get(i));
                    }
                }
            });
            //根据品牌型号产地合并
            Map<String,AuxiliaryInspectionVO> map = new LinkedHashMap<>();
            Map<String, CountryVO> countryVOMap = Maps.newHashMap();
            dataList.stream().forEach(data ->{
                if(StringUtils.isEmpty(data.getModel())){
                    throw new ServiceException(String.format("箱号【%s】型号不能为空",data.getRowNo()));
                }
                if(StringUtils.isEmpty(data.getBrand())){
                    throw new ServiceException(String.format("箱号【%s】品牌不能为空",data.getRowNo()));
                }
                if(StringUtils.isEmpty(data.getCountry())){
                    throw new ServiceException(String.format("箱号【%s】产地不能为空",data.getRowNo()));
                }
                CountryVO countryVO = countryVOMap.get(StringUtils.removeSpecialSymbol(data.getCountry()));
                if(Objects.isNull(countryVO)){
                    //验证产地是否正确
                    countryVO = systemCacheService.getCountryByName(StringUtils.removeSpecialSymbol(data.getCountry()));
                }
                if(Objects.isNull(countryVO)){
                    throw new ServiceException(String.format("箱号【%s】产地填写错误",data.getRowNo()));
                }else{
                    countryVOMap.put(StringUtils.removeSpecialSymbol(data.getCountry()),countryVO);
                }
                AuxiliaryInspectionVO vo = beanMapper.map(data,AuxiliaryInspectionVO.class);
                vo.setModel(StringUtils.removeSpecialSymbol(vo.getModel()));
                vo.setBrand(StringUtils.removeSpecialSymbol(vo.getBrand()));
                vo.setCountry(StringUtils.removeSpecialSymbol(vo.getCountry()));
                vo.setRowNo(StringUtils.removeSpecialSymbol(vo.getRowNo()).replace("，", ","));
                String key = String.format("%s||%s||%s",data.getModel(),data.getBrand(),data.getCountry());
                AuxiliaryInspectionVO mapVo = map.get(key);
                if(Objects.nonNull(mapVo)){
                    vo.setCarton(vo.getCarton()+mapVo.getCarton());
                    vo.setQuantity(vo.getQuantity().add(mapVo.getQuantity()).setScale(2,BigDecimal.ROUND_HALF_UP));
                    vo.setNetWeight(vo.getNetWeight().add(mapVo.getNetWeight()).setScale(4,BigDecimal.ROUND_HALF_UP));
                    vo.setGrossWeight(vo.getGrossWeight().add(mapVo.getGrossWeight()).setScale(4,BigDecimal.ROUND_HALF_UP));
                    if(StringUtils.isNotEmpty(mapVo.getRowNo()) && StringUtils.isNotEmpty(vo.getRowNo())){
                        List<String> rows = Lists.newArrayList();
                        if(StringUtils.isNotEmpty(mapVo.getRowNo())){
                            rows = new ArrayList<>(Arrays.asList(mapVo.getRowNo().replace("，",",").split(",")));
                        }
                        if(StringUtils.isNotEmpty(vo.getRowNo())){
                            List<String> rw = Arrays.asList(vo.getRowNo().replace("，", ",").split(","));
                            for(String str : rw){
                                if(!rows.contains(str)){
                                    rows.add(str);
                                }
                            }
                        }
                        Collections.sort(rows, Comparator.naturalOrder());
                        vo.setRowNo(String.join(",",rows));
                    }
                }
                map.put(key,vo);
            });
            List<AuxiliaryInspectionVO> auxiliaryInspectionVOList = new ArrayList<>();
            map.entrySet().forEach(obj ->{
                auxiliaryInspectionVOList.add(obj.getValue());
            });
            List<ImpOrderMemberVO> members = impOrderMemberService.findOrderMaterielMember(orderId);
            InspectionPlusVO plusVO = new InspectionPlusVO();
            plusVO.setMembers(members);
            plusVO.setAuxiliaryInspections(auxiliaryInspectionVOList);
            return plusVO;
        }catch(ServiceException se){
            throw se;
        }catch (Exception e){
            log.error("解析Excel出错：",e);
            throw new ServiceException("解析Excel出错");
        }
    }
    //分摊净重
    private void shareNetWeight(BigDecimal netWeight,BigDecimal totalQuantity,AuxiliaryInspectionExcel auxiliaryInspectionExcel){
        BigDecimal quantity = StringUtils.rounded4(auxiliaryInspectionExcel.getQuantity());
        auxiliaryInspectionExcel.setNetWeight(netWeight.divide(totalQuantity,20,BigDecimal.ROUND_HALF_UP).multiply(quantity).setScale(4,BigDecimal.ROUND_HALF_UP).toString());
    }
    //分摊毛重
    private void shareGrossWeight(BigDecimal grossWeight,BigDecimal totalQuantity,AuxiliaryInspectionExcel auxiliaryInspectionExcel){
        BigDecimal quantity = StringUtils.rounded4(auxiliaryInspectionExcel.getQuantity());
        auxiliaryInspectionExcel.setGrossWeight(grossWeight.divide(totalQuantity,20,BigDecimal.ROUND_HALF_UP).multiply(quantity).setScale(4,BigDecimal.ROUND_HALF_UP).toString());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void confirmInspection(Long id) {
        ImpOrder impOrder = super.getById(id);
        TsfPreconditions.checkArgument(Objects.nonNull(impOrder),new ServiceException("订单不存在"));
        DomainOprationEnum oprationEnum = DomainOprationEnum.ORDER_INSPECTION;
        //验证状态是否可以执行操作
        DomainStatus.getInstance().check(oprationEnum, impOrder.getStatusId());
        TsfPreconditions.checkArgument(impOrder.getTotalCartonNum()>0,new ServiceException("总箱数不能为零"));
        TsfPreconditions.checkArgument(impOrder.getTotalNetWeight().compareTo(BigDecimal.ZERO)==1,new ServiceException("总净重必须大于零"));
        TsfPreconditions.checkArgument(impOrder.getTotalCrossWeight().compareTo(BigDecimal.ZERO)==1,new ServiceException("总毛重必须大于零"));
        TsfPreconditions.checkArgument(impOrder.getTotalCrossWeight().compareTo(impOrder.getTotalNetWeight())>=0,new ServiceException("总毛重不能小于总净重"));
        //原始单据状态
        ImpOrderStatusEnum historyStatus = ImpOrderStatusEnum.of(impOrder.getStatusId());
        //获取包含物料的产品明细
        List<ImpOrderMemberVO> memberVOS = impOrderMemberService.findOrderMaterielMember(id);
        //获取预绑定数据
        Map<Long,List<OrderMemberReceivingNo>> ornMap = Maps.newHashMap();
        List<OrderMemberReceivingNo> omrnList = orderMemberReceivingNoService.findByOrderId(impOrder.getId());
        omrnList.stream().forEach(omrn ->{
            List<OrderMemberReceivingNo> items = ornMap.get(omrn.getOrderMemberId());
            if(CollUtil.isEmpty(items)){
                items = Lists.newArrayList();
            }
            items.add(omrn);
            ornMap.put(omrn.getOrderMemberId(),items);
        });
        //更新订单明细数据
        List<ImpOrderMember> updateOrderMembers = Lists.newArrayList();
        //入库单明细数据
        List<ReceivingNoteMember> rnmList = Lists.newArrayList();
        //入库单主单
        Map<String,ReceivingNote> rnMap = Maps.newHashMap();
        //入库单订单明细绑定
        List<OrderReceivingNoteMember> ornmList = Lists.newArrayList();
        memberVOS.stream().forEach(member ->{
            TsfPreconditions.checkArgument(MaterielStatusEnum.CLASSED.getCode().equals(member.getMaterielStatusId()),new ServiceException(String.format("第【%d】行【%s】未完成归类,请联系关务归类",member.getRowNo(),member.getModel())));
            BigDecimal bindQty = BigDecimal.ZERO;
            List<OrderMemberReceivingNo> items = ornMap.get(member.getId());
            List<String> receivingNos = Lists.newArrayList();
            if(CollUtil.isNotEmpty(items)){
                //如果只绑定一个入库号默认为下单数量
                if(items.size()==1&&items.get(0).getQuantity().compareTo(member.getQuantity())!=0){
                    items.get(0).setQuantity(member.getQuantity());
                    orderMemberReceivingNoService.updateById(items.get(0));
                }
                for(OrderMemberReceivingNo item : items){
                    bindQty = bindQty.add(item.getQuantity());
                    receivingNos.add(item.getReceivingNo());
                    //获取入库单主单
                    ReceivingNote receivingNote = rnMap.get(item.getReceivingNo());
                    if(Objects.isNull(receivingNote)){
                        receivingNote = receivingNoteService.findByDocNo(item.getReceivingNo());
                        TsfPreconditions.checkArgument(Objects.nonNull(impOrder),new ServiceException(String.format("第【%d】行【%s】入库单号不存在",member.getRowNo(),item.getReceivingNo())));
                    }
                    rnMap.put(item.getReceivingNo(),receivingNote);

                    //生成入库单明细数据
                    ReceivingNoteMember rnm = new ReceivingNoteMember();
                    rnm.setId(snowflake.nextId());
                    rnm.setReceivingNoteId(receivingNote.getId());
                    rnm.setRowNo(member.getRowNo());
                    rnm.setModel(member.getModel());
                    rnm.setBrand(member.getDecBrand());
                    rnm.setName(member.getDecName());
                    rnm.setSpec(member.getSpec());
                    rnm.setGoodsCode(member.getGoodsCode());
                    rnm.setCountry(member.getCountry());
                    rnm.setCountryName(member.getCountryName());
                    rnm.setUnitCode(member.getUnitCode());
                    rnm.setUnitName(member.getUnitName());
                    rnm.setQuantity(item.getQuantity());
                    rnm.setNetWeight(member.getNetWeight());
                    rnm.setGrossWeight(member.getGrossWeight());
                    rnm.setCartonNo(member.getCartonNo());
                    rnm.setCartonNum(member.getCartonNum());
                    rnm.setOrderNo(impOrder.getDocNo());
                    rnmList.add(rnm);

                    //入库单订单绑定明细
                    OrderReceivingNoteMember ornm = new OrderReceivingNoteMember();
                    ornm.setId(snowflake.nextId());
                    ornm.setOrderNo(impOrder.getDocNo());
                    ornm.setOrderMemberId(member.getId());
                    ornm.setReceivingNo(item.getReceivingNo());
                    ornm.setReceivingNoteMemberId(rnm.getId());
                    ornm.setQuantity(item.getQuantity());
                    ornm.setIsLock(Boolean.TRUE);
                    ornm.setIsOutStock(Boolean.FALSE);
                    ornmList.add(ornm);
                }
            }else{
                throw new ServiceException(String.format("第【%d】行【%s】未绑定入库单号",member.getRowNo(),member.getModel()));
            }
            if(member.getQuantity().compareTo(bindQty)!=0){
                throw new ServiceException(String.format("第【%d】行【%s】下单数量与入库单绑定数量不一致，请检查",member.getRowNo(),member.getModel()));
            }
            //更新订单明细数据
            ImpOrderMember update = new ImpOrderMember();
            update.setId(member.getId());
            update.setReceivingQuantity(bindQty);
            update.setReceivingNoteNo(String.join(",",receivingNos));
            update.setBrand(member.getDecBrand());
            update.setName(member.getDecName());
            updateOrderMembers.add(update);
        });
        //更新订单明细数据
        impOrderMemberService.batchUpdatePartData(updateOrderMembers);
        //保存入库单明细
        receivingNoteMemberService.savaBatch(rnmList);
        //保存绑定信息
        orderReceivingNoteMemberService.savaBatch(ornmList);
        //更新入库单订单号信息
        for(Map.Entry<String,ReceivingNote> map : rnMap.entrySet()){
            receivingNoteService.updateReceivingNoteOrderNo(map.getValue());
        }
        //更新订单状态(待确认进口)
        ImpOrderStatusEnum statusEnum = ImpOrderStatusEnum.WAIT_CONFIRM_IMP;
        impOrder.setStatusId(statusEnum.getCode());
        //计算订单费用
        impOrderCostService.calculationCost(impOrder);
        //记录历史状态
        statusHistoryService.saveHistory(oprationEnum,
                impOrder.getId().toString(),ImpOrder.class.getName(),
                historyStatus.getCode(),historyStatus.getName(),
                statusEnum.getCode(),statusEnum.getName(),
                "验货确认"
        );
        //清除验货确认任务提示
        taskNoticeContentService.deleteTaskNotice(DomainTypeEnum.IMPORDER.getCode(), impOrder.getId(), oprationEnum.getCode());

        //任务通知
        TaskNoticeContentDTO taskNoticeContentDTO = new TaskNoticeContentDTO();
        taskNoticeContentDTO.setDocumentType(DomainTypeEnum.IMPORDER.getCode());
        taskNoticeContentDTO.setDocumentId(impOrder.getId().toString());
        taskNoticeContentDTO.setCustomerId(impOrder.getCustomerId());
        taskNoticeContentDTO.setOperationCode(DomainOprationEnum.ORDER_CONFIRMIMP.getCode());
        taskNoticeContentDTO.setContent(String.format("进口订单【%s】已验货完成，请尽快确认进口", impOrder.getDocNo()));
        taskNoticeContentDTO.setQueryParamsMap(ImmutableMap.of("docNo",impOrder.getDocNo()));
        taskNoticeContentService.add(taskNoticeContentDTO);
    }


    @Override
    public List<SplitOrderMemberVO> initSelfHelpSplit(Long orderId, Integer quantity) {
        if(quantity<1||quantity>50){
            throw new ServiceException("数量必须为1~50");
        }
        ImpOrder impOrder = super.getById(orderId);
        TsfPreconditions.checkArgument(Objects.nonNull(impOrder),new ServiceException("订单不存在"));
        DomainOprationEnum oprationEnum = DomainOprationEnum.ORDER_INSPECTION;
        //验证状态是否可以执行操作
        DomainStatus.getInstance().check(oprationEnum, impOrder.getStatusId());

        TsfPreconditions.checkArgument(impOrder.getTotalCartonNum()>0,new ServiceException("总箱数不能为零"));
        TsfPreconditions.checkArgument(impOrder.getTotalNetWeight().compareTo(BigDecimal.ZERO)==1,new ServiceException("总净重必须大于零"));
        TsfPreconditions.checkArgument(impOrder.getTotalCrossWeight().compareTo(BigDecimal.ZERO)==1,new ServiceException("总毛重必须大于零"));
        TsfPreconditions.checkArgument(impOrder.getTotalCrossWeight().compareTo(impOrder.getTotalNetWeight())>=0,new ServiceException("总毛重不能小于总净重"));
        //获取包含物料的产品明细
        List<ImpOrderMemberVO> memberVOS = impOrderMemberService.findOrderMaterielMember(impOrder.getId());
        if(quantity>=memberVOS.size()){
            throw new ServiceException("拆单数量必须小于产品数量");
        }
        //获取预绑定数据
        Map<Long,List<OrderMemberReceivingNo>> ornMap = Maps.newHashMap();
        List<OrderMemberReceivingNo> omrnList = orderMemberReceivingNoService.findByOrderId(impOrder.getId());
        omrnList.stream().forEach(omrn ->{
            List<OrderMemberReceivingNo> items = ornMap.get(omrn.getOrderMemberId());
            if(CollUtil.isEmpty(items)){
                items = Lists.newArrayList();
            }
            items.add(omrn);
            ornMap.put(omrn.getOrderMemberId(),items);
        });
        // O证产品(监管条件 存在O) 一条一单
        List<ImpOrderMemberVO> ozList = Lists.newArrayList();
        // 商检产品单独一单(监管条件 存在A 或 检验检疫 存在L)
        List<ImpOrderMemberVO> sjList = Lists.newArrayList();
        // 其它产品
        List<ImpOrderMemberVO> otList = Lists.newArrayList();
        memberVOS.stream().forEach(member -> {
            TsfPreconditions.checkArgument(MaterielStatusEnum.CLASSED.getCode().equals(member.getMaterielStatusId()), new ServiceException(String.format("第【%d】行【%s】未完成归类,请联系关务归类", member.getRowNo(), member.getModel())));
            BigDecimal bindQty = BigDecimal.ZERO;
            List<OrderMemberReceivingNo> items = ornMap.get(member.getId());
            if(CollUtil.isNotEmpty(items)){
                //如果只绑定一个入库号默认为下单数量
                if(items.size()==1&&items.get(0).getQuantity().compareTo(member.getQuantity())!=0){
                    items.get(0).setQuantity(member.getQuantity());
                }
                for(OrderMemberReceivingNo item : items) {
                    bindQty = bindQty.add(item.getQuantity());
                }
            }else{
                throw new ServiceException(String.format("第【%d】行【%s】未绑定入库单号",member.getRowNo(),member.getModel()));
            }
            if(member.getQuantity().compareTo(bindQty)!=0){
                throw new ServiceException(String.format("第【%d】行【%s】下单数量与入库单绑定数量不一致，请检查",member.getRowNo(),member.getModel()));
            }
            if(StringUtils.isNotEmpty(member.getCsc()) && member.getCsc().toUpperCase().indexOf("O") != -1){
                // O证产品(监管条件 存在O) 一条一单
                ozList.add(member);
            }else if((StringUtils.isNotEmpty(member.getCsc()) && member.getCsc().toUpperCase().indexOf("A") != -1) || (StringUtils.isNotEmpty(member.getIaqr()) && member.getIaqr().toUpperCase().indexOf("L") != -1)){
                // 商检产品单独一单(监管条件 存在A 或 检验检疫 存在L)
                sjList.add(member);
            }else{
                otList.add(member);
            }
        });
        List<SplitOrderMemberVO> result = Lists.newArrayList();
        result.addAll(splitOrderMember(orderId,otList,quantity));
        result.addAll(splitOrderMember(orderId,sjList,quantity));
        result.addAll(splitOrderMember(orderId,ozList,1));
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveSelfHelpSplit(SelfHelpSplitDTO dto) {
        ImpOrder impOrder = super.getById(dto.getOrderId());
        TsfPreconditions.checkArgument(Objects.nonNull(impOrder),new ServiceException("订单不存在"));
        DomainOprationEnum oprationEnum = DomainOprationEnum.ORDER_SPLIT;
        //验证状态是否可以执行操作
        DomainStatus.getInstance().check(oprationEnum, impOrder.getStatusId());
        List<SelfHelpSplitMemberDTO> memberDTOS = dto.getMembers();
        List<SelfHelpSplitMemberDTO> newMemberList = Lists.newArrayList();
        for(SelfHelpSplitMemberDTO splitMemberDTO : memberDTOS){
            if(CollUtil.isNotEmpty(splitMemberDTO.getIds())){
                newMemberList.add(splitMemberDTO);
            }
        }
        // 查询原始订单明细数据
        List<ImpOrderMember> oldMemberList = impOrderMemberService.getByOrderId(impOrder.getId());
        // 查询原始订单历史数据
        List<ImpOrderMemberHistory> oldMemberHistoryList = impOrderMemberHistoryService.getByOrderId(impOrder.getId());
        Map<Long,ImpOrderMember> impOrderMemberMap = oldMemberList.stream().collect(Collectors.toMap(ImpOrderMember::getId, Function.identity()));
        Map<Long,ImpOrderMemberHistory> impOrderMemberHistoryMap = oldMemberHistoryList.stream().collect(Collectors.toMap(ImpOrderMemberHistory::getId, Function.identity()));
        List<SelfHelpSplitMemberDTO> members = dto.getMembers();
        if(CollUtil.isEmpty(members)||members.size()<2){
            throw new ServiceException("请至少拆分出一份订单");
        }
        // 查询订单物流信息
        ImpOrderLogistics impOrderLogistics = impOrderLogisticsService.getById(impOrder.getId());
        // 从第二个单开始新单
        for(int i=1;i<members.size();i++){
            SelfHelpSplitMemberDTO splitMemberDTO = members.get(i);
            ImpOrder io = beanMapper.map(impOrder,ImpOrder.class);
            io.setId(null);
            io.setPayVal(BigDecimal.ZERO);
            io.setSalesContractNo("");
            io.setInvoiceNo("");
            io.setPaymentNo("");
            io.setDocNo(serialNumberService.generateDocNo(SerialNumberTypeEnum.IMP_ORDER));
            super.saveNonNull(io);
            // 保存物流信息
            ImpOrderLogistics newImpOrderLogistics = beanMapper.map(impOrderLogistics,ImpOrderLogistics.class);
            newImpOrderLogistics.setId(io.getId());
            newImpOrderLogistics.setImpOrderId(io.getId());
            impOrderLogisticsService.saveNonNull(newImpOrderLogistics);
            // 订单明细数据
            List<ImpOrderMember> iomList = Lists.newArrayList();
            // 订单明细历史数据
            List<ImpOrderMemberHistory> iomhList = Lists.newArrayList();
            if(CollUtil.isEmpty(splitMemberDTO.getIds())){
                throw new ServiceException(String.format("第【%s】个订单未拆分出订单明细",i));
            }
            //订单数据合计
            io.setTotalPrice(BigDecimal.ZERO);//委托金额
            io.setDecTotalPrice(BigDecimal.ZERO);//报关金额
            io.setTotalCartonNum(0);//总箱数
            io.setTotalMember(splitMemberDTO.getIds().size());//产品条数
            io.setTotalNetWeight(BigDecimal.ZERO);//总净重
            io.setTotalCrossWeight(BigDecimal.ZERO);//总毛重
            for(int j=0;j<splitMemberDTO.getIds().size();j++){
                Long mid = splitMemberDTO.getIds().get(j);
                ImpOrderMember iom = impOrderMemberMap.get(mid);
                if(Objects.isNull(iom)){
                    throw new ServiceException(String.format("第【%s】个订单第【%s】条明细不存在",i+1,j+1));
                }
                iom.setRowNo(j+1);
                iom.setImpOrderId(io.getId());
                iomList.add(iom);
                impOrderMemberMap.remove(mid);
                // 数据统计
                io.setTotalPrice(io.getTotalPrice().add(iom.getTotalPrice()).setScale(2,BigDecimal.ROUND_HALF_UP));
                io.setDecTotalPrice(io.getDecTotalPrice().add(iom.getDecTotalPrice()).setScale(2,BigDecimal.ROUND_HALF_UP));
                io.setTotalCartonNum(io.getTotalCartonNum()+iom.getCartonNum());
                io.setTotalNetWeight(io.getTotalNetWeight().add(iom.getNetWeight()).setScale(4,BigDecimal.ROUND_HALF_UP));
                io.setTotalCrossWeight(io.getTotalCrossWeight().add(iom.getGrossWeight()).setScale(4,BigDecimal.ROUND_HALF_UP));

                ImpOrderMemberHistory iomh = impOrderMemberHistoryMap.get(mid);
                if(Objects.nonNull(iomh)){
                    iomh.setRowNo(j+1);
                    iomh.setImpOrderId(io.getId());
                    iomhList.add(iomh);
                }
            }
            if(io.getTotalCartonNum()==0){
                throw new ServiceException(String.format("第【%s】个订单总箱数必须大于零",i+1));
            }
            if(io.getTotalNetWeight().compareTo(BigDecimal.ZERO)<1){
                throw new ServiceException(String.format("第【%s】个订单总净重必须大于零",i+1));
            }
            if(io.getTotalNetWeight().compareTo(io.getTotalCrossWeight())==1){
                throw new ServiceException(String.format("第【%s】个订单总净重不能大于总毛重",i+1));
            }
            //原始单据状态
            ImpOrderStatusEnum historyStatus = ImpOrderStatusEnum.of(io.getStatusId());
            // 待审核状态
            ImpOrderStatusEnum statusEnum = ImpOrderStatusEnum.WAIT_EXAMINE;
            io.setStatusId(statusEnum.getCode());
            // 修改订单主单
            super.updateById(io);
            // 修改订单明细
            impOrderMemberService.batchUpdateSplitMembers(iomList);
            // 修改订单明细历史数据
            impOrderMemberHistoryService.batchUpdateSplitMembers(iomhList);
            //记录历史状态
            statusHistoryService.saveHistory(oprationEnum,
                    io.getId().toString(),ImpOrder.class.getName(),
                    historyStatus.getCode(),historyStatus.getName(),
                    statusEnum.getCode(),statusEnum.getName(),
                    "拆单原始订单号："+impOrder.getDocNo()
            );
            //重新计算订单费用
            impOrderCostService.calculationCost(io);
        }

        // 更新原始订单
        SelfHelpSplitMemberDTO splitMemberDTO = members.get(0);
        if(splitMemberDTO.getIds().size()!=impOrderMemberMap.size()){
            throw new ServiceException("订单明细与拆单明细不一致请刷新页面重试");
        }
        //订单数据合计
        impOrder.setTotalPrice(BigDecimal.ZERO);//委托金额
        impOrder.setDecTotalPrice(BigDecimal.ZERO);//报关金额
        impOrder.setTotalCartonNum(0);//总箱数
        impOrder.setTotalMember(splitMemberDTO.getIds().size());//产品条数
        impOrder.setTotalNetWeight(BigDecimal.ZERO);//总净重
        impOrder.setTotalCrossWeight(BigDecimal.ZERO);//总毛重
        // 订单明细数据
        List<ImpOrderMember> iomList = Lists.newArrayList();
        for(int j=0;j<splitMemberDTO.getIds().size();j++){
            Long mid = splitMemberDTO.getIds().get(j);
            ImpOrderMember iom = impOrderMemberMap.get(mid);
            if(Objects.isNull(iom)){
                throw new ServiceException(String.format("第【1】个订单第【%s】条明细不存在",j+1));
            }
            iom.setRowNo(j+1);
            iomList.add(iom);
            // 数据统计
            impOrder.setTotalPrice(impOrder.getTotalPrice().add(iom.getTotalPrice()).setScale(2,BigDecimal.ROUND_HALF_UP));
            impOrder.setDecTotalPrice(impOrder.getDecTotalPrice().add(iom.getDecTotalPrice()).setScale(2,BigDecimal.ROUND_HALF_UP));
            impOrder.setTotalCartonNum(impOrder.getTotalCartonNum()+iom.getCartonNum());
            impOrder.setTotalNetWeight(impOrder.getTotalNetWeight().add(iom.getNetWeight()).setScale(4,BigDecimal.ROUND_HALF_UP));
            impOrder.setTotalCrossWeight(impOrder.getTotalCrossWeight().add(iom.getGrossWeight()).setScale(4,BigDecimal.ROUND_HALF_UP));
        }
        if(impOrder.getTotalCartonNum()==0){
            throw new ServiceException("第【1】个订单总箱数必须大于零");
        }
        if(impOrder.getTotalNetWeight().compareTo(BigDecimal.ZERO)<1){
            throw new ServiceException("第【1】个订单总净重必须大于零");
        }
        if(impOrder.getTotalNetWeight().compareTo(impOrder.getTotalCrossWeight())==1){
            throw new ServiceException("第【1】个订单总净重不能大于总毛重");
        }
        // 修改订单明细
        impOrderMemberService.batchUpdateSplitMembers(iomList);
        super.updateById(impOrder);
        //重新计算订单费用
        impOrderCostService.calculationCost(impOrder);
    }

    // 明细按照条数拆单
    private List<SplitOrderMemberVO> splitOrderMember(Long orderId,List<ImpOrderMemberVO> memberList,Integer quantity){
        List<SplitOrderMemberVO> result = Lists.newArrayList();
        if(CollUtil.isNotEmpty(memberList)){
            List<ImpOrderMemberVO> list = Lists.newArrayList();
            for(int i=1;i<=memberList.size();i++){
                list.add(memberList.get(i-1));
                if(i%quantity==0){
                    result.add(new SplitOrderMemberVO(orderId,list));
                    list = Lists.newArrayList();
                }
            }
            if(CollUtil.isNotEmpty(list)){
                result.add(new SplitOrderMemberVO(orderId,list));
            }
        }
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void relieveReceivingNoteBind(ImpOrder impOrder) {
        List<String> receivingNos = Lists.newArrayList();
        List<Long> ornmIds = Lists.newArrayList();
        List<Long> ornmRmemberIds = Lists.newArrayList();
        //根据订单查询绑定的入库单
        List<OrderReceivingNoteMember> ornmList = orderReceivingNoteMemberService.findByOrderNo(impOrder.getDocNo());
        ornmList.stream().forEach(ornm ->{
            if(!receivingNos.contains(ornm.getReceivingNo())){
                receivingNos.add(ornm.getReceivingNo());
            }
            ornmIds.add(ornm.getId());
            ornmRmemberIds.add(ornm.getReceivingNoteMemberId());
        });
        //解除入库单绑定
        orderReceivingNoteMemberService.removeByIds(ornmIds);
        // 根据入库单明细删除出库单信息
        deliveryNoteService.removeByReceivingNoteMember(ornmRmemberIds);
        //删除入库单明细
        receivingNoteMemberService.removeByIds(ornmRmemberIds);
        //更新入库单已绑定的订单号
        receivingNos.stream().forEach(rno ->{
            receivingNoteService.updateReceivingNoteOrderNo(rno);
        });
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void completeRisk(Long orderId, Boolean isPass, String memo) {
        ImpOrder impOrder = super.getById(orderId);
        TsfPreconditions.checkArgument(Objects.nonNull(impOrder),new ServiceException("订单不存在"));
        DomainOprationEnum oprationEnum = DomainOprationEnum.ORDER_COMPLETE_RISK;
        //验证状态是否可以执行操作
        DomainStatus.getInstance().check(oprationEnum, impOrder.getStatusId());
        //原始单据状态
        ImpOrderStatusEnum historyStatus = ImpOrderStatusEnum.of(impOrder.getStatusId());
        //更新订单状态(待确认进口)
        ImpOrderStatusEnum statusEnum = ImpOrderStatusEnum.WAIT_CONFIRM_IMP;
        impOrder.setStatusId(statusEnum.getCode());
        super.updateById(impOrder);
        //记录历史状态
        statusHistoryService.saveHistory(oprationEnum,
                impOrder.getId().toString(),ImpOrder.class.getName(),
                historyStatus.getCode(),historyStatus.getName(),
                statusEnum.getCode(),statusEnum.getName(),
                (isPass?"风控审核通过":"风控审核不通过").concat("："+StringUtils.removeSpecialSymbol(memo))
        );
        //任务通知
        TaskNoticeContentDTO taskNoticeContentDTO = new TaskNoticeContentDTO();
        taskNoticeContentDTO.setDocumentType(DomainTypeEnum.IMPORDER.getCode());
        taskNoticeContentDTO.setDocumentId(impOrder.getId().toString());
        taskNoticeContentDTO.setCustomerId(impOrder.getCustomerId());
        taskNoticeContentDTO.setOperationCode(DomainOprationEnum.ORDER_CONFIRMIMP.getCode());
        taskNoticeContentDTO.setContent(String.format("进口订单【%s】已完成风控审批，请尽快确认进口", impOrder.getDocNo()));
        taskNoticeContentDTO.setQueryParamsMap(ImmutableMap.of("docNo",impOrder.getDocNo()));
        taskNoticeContentService.add(taskNoticeContentDTO);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public int updateTransportNo(Long orderId, String transportNo) {
        return impOrderMapper.updateTransportNo(orderId,transportNo);
    }

    @Override
    public List<BindOrderVO> waybillCanBindOrderList(Boolean isCharterCar) {
        return impOrderMapper.listCanBind(isCharterCar);
    }

    @Override
    public List<BindOrderVO> waybillBindedOrderList(String transportNo) {
        return impOrderMapper.listBinded(transportNo);
    }

    @Override
    public int getWaybillBindOrderNumber(String transportNo) {
        TsfWeekendSqls wheres = TsfWeekendSqls.<ImpOrder>custom().andEqualTo(false,ImpOrder::getTransportNo,transportNo);
        return impOrderMapper.selectCountByExample(Example.builder(ImpOrder.class).where(wheres).build());
    }

    @Override
    public void resetTransportNo(Long id) {
        impOrderMapper.resetTransportNo(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void setupDeclaration(SetupDeclarationDTO dto) {
        ImpOrder impOrder = super.getById(dto.getId());
        TsfPreconditions.checkArgument(Objects.nonNull(impOrder),new ServiceException("订单不存在"));
        TsfPreconditions.checkArgument(Objects.equals(impOrder.getIsImp(),Boolean.FALSE),new ServiceException("当前订单已经生成报关单无法修改"));
        //订单成交方式
        TransactionModeEnum transactionMode = TransactionModeEnum.of(impOrder.getTransactionMode());
        switch (transactionMode){
            case CIF:
                impOrder.setTransCosts("");//运费
                impOrder.setInsuranceCosts("");//保费
                impOrder.setMiscCosts("");//杂费
                break;
            case FOB:
                impOrder.setTransCosts(dto.getFeeCurr()+"/"+dto.getFeeRate()+"/"+dto.getFeeMark());//运费
                impOrder.setInsuranceCosts(dto.getInsurCurr()+"/"+dto.getInsurRate()+"/"+dto.getInsurMark());//保费
                impOrder.setMiscCosts(dto.getOtherCurr()+"/"+dto.getOtherRate()+"/"+dto.getOtherMark());//杂费
                break;
            default:
                throw new ServiceException("成交方式错误");
        }
        //报关单模板
        impOrder.setDeclarationTempId(dto.getTempId());
        //重新计算订单费用
        impOrderCostService.calculationCost(impOrder);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void setInvoiceNo(Long id,String orderNo,String invoiceNo) {
        impOrderMapper.setInvoiceNo(id,orderNo,invoiceNo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateOrderPaymentNo(Long id, String paymentNo) {
        impOrderMapper.updateOrderPaymentNo(id,paymentNo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateSalesContractNo(String impOrderNo, String salesContractNo) {
        impOrderMapper.updateSalesContractNo(impOrderNo,salesContractNo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void impOrderClearance(List<BindOrderVO> bindedOrders) {
        ImpOrderStatusEnum statusEnum = ImpOrderStatusEnum.CLEARED;
        bindedOrders.stream().forEach(border ->{
            ImpOrderStatusEnum historyStatus = ImpOrderStatusEnum.of(border.getStatusId());
            TsfPreconditions.checkArgument(Objects.equals(ImpOrderStatusEnum.WAIT_CLEARANCE,historyStatus),new ServiceException(String.format("订单【%s】不处于待通关状态",border.getDocNo())));
            ImpOrder updateOrder = new ImpOrder();
            updateOrder.setId(border.getId());
            updateOrder.setStatusId(statusEnum.getCode());
            impOrderMapper.updateByPrimaryKeySelective(updateOrder);

            //记录历史状态
            statusHistoryService.saveHistory(DomainOprationEnum.CROSS_BORDER_WAYBILL_SIGN,
                    border.getId().toString(),ImpOrder.class.getName(),
                    historyStatus.getCode(),historyStatus.getName(),
                    statusEnum.getCode(),statusEnum.getName(),
                    String.format("跨境运单签收自动触发"),"系统");
        });
    }

    @Override
    public List<ImpOrderAdjustCostVO> selectAdjustOrder(String orderNo) {
        Map<String,Object> params = Maps.newHashMap();
        params.put("orderNo",orderNo);
        return  impOrderMapper.selectAdjustOrder(params);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void clientRemove(Long id) {
        ImpOrder impOrder = super.getById(id);
        Optional.ofNullable(impOrder).orElseThrow(()->new ServiceException("订单信息不存在，请确认是否已经被删除"));
        PermissionUtil.checkClientCustomerPermission(impOrder);
        removeOrder(impOrder);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void remove(Long id) {
        ImpOrder impOrder = super.getById(id);
        removeOrder(impOrder);
    }

    @Transactional(rollbackFor = Exception.class)
    public void removeOrder(ImpOrder impOrder){
        Optional.ofNullable(impOrder).orElseThrow(()->new ServiceException("订单信息不存在，请确认是否已经被删除"));
        //验证状态是否可以执行操作
        DomainStatus.getInstance().check(DomainOprationEnum.ORDER_REMOVE, impOrder.getStatusId());
        //检查是否申请付汇
        List<String> payDocNos = paymentAccountMemberService.findByOrderIdByPayNos(impOrder.getId());
        TsfPreconditions.checkArgument(CollUtil.isEmpty(payDocNos),new ServiceException("订单已申请付汇，不允许删除"));
        // 检查销售合同
        ImpSalesContract impSalesContract = impSalesContractService.findByOrderId(impOrder.getId());
        if(Objects.nonNull(impSalesContract)){
            throw new ServiceException("当前订单已经创建销售合同请先处理");
        }
        // 检查订单费用是否存在核销
        List<ImpOrderCost> costs = impOrderCostService.findByOrderId(impOrder.getId());
        if(CollUtil.isNotEmpty(costs)){
            costs.stream().forEach(cost ->{
                if(cost.getAcceAmount().compareTo(BigDecimal.ZERO) == 1){
                    throw new ServiceException("当前订单存在应收已核销请先处理");
                }
                impOrderCostService.removeById(cost.getId());
            });
        }
        //删除订单物流信息
        impOrderLogisticsService.removeByImpOrderId(impOrder.getId());
        List<ImpOrderMember> impOrderMembers = impOrderMemberService.getByOrderId(impOrder.getId());
        if(CollUtil.isNotEmpty(impOrderMembers)){
            impOrderMembers.stream().forEach(member ->{
                // 删除辅助入库单绑定数据
                orderMemberReceivingNoService.removeByOrderMemberId(member.getId());
            });
            // 删除明细信息
            impOrderMemberService.removeByImpOrderId(impOrder.getId());
        }
        // 删除订单明细历史数据
        impOrderMemberHistoryService.removeByOrderId(impOrder.getId());
        // 删除费用变更记录
        costChangeRecordService.removeByOrderId(impOrder.getId());
        // 删除审价
        impOrderPriceService.removeByOrderId(impOrder.getId());
        //删除历史状态
        statusHistoryService.removeHistory(impOrder.getId().toString(), ImpOrder.class.getName());
        //清空任务
        taskNoticeContentService.deleteTaskNotice(DomainTypeEnum.IMPORDER.getCode(), impOrder.getId(), "");
        try {
            super.removeById(impOrder.getId());
        } catch (DataIntegrityViolationException e) {
            log.error("删除订单出错：",e);
            throw new ServiceException("当前订单已经在操作流程中，请勿删除");
        }
    }

    @Override
    public Integer editOrderSize() {
        //待修改
        return impOrderMapper.getCountInStatusId(SecurityUtil.getCurrentCustomerId(),ImpOrderStatusEnum.WAIT_EDIT.getCode());
    }

    @Override
    public List<ImportOrderMemberVO> readDataFromMemberImport(MultipartFile file) {
        Stopwatch stopwatch = Stopwatch.createStarted();
        List<OrderMemberExcel> dataList;
        try {
            dataList = ExcelUtil.readExcel(file, OrderMemberExcel.class, 1);
        } catch (Exception e) {
            log.error("读取导入的excel文件异常",e);
            throw new ServiceException("导入数据异常，请仔细检查您的导入文件是否符合模板要求");
        }
        if(CollectionUtils.isEmpty(dataList)) {
            throw new ServiceException("本次没有可以导入的数据");
        }
        //导入最大数目检查
        TsfPreconditions.checkArgument(dataList.size() <= uploadMaxmum,new ServiceException(String.format("您本次导入的数据超过%d条的上限了",uploadMaxmum)));
        //特殊符号处理
        dataList.stream().forEach(data->{
            data.setBrand(StringUtils.removeSpecialSymbol(data.getBrand()));
            data.setModel(StringUtils.removeSpecialSymbol(data.getModel()));
            data.setName(StringUtils.removeSpecialSymbol(data.getName()));
            data.setUnitName(StringUtils.removeSpecialSymbol(data.getUnitName()));
            data.setQuantity(StringUtils.removeSpecialSymbol(data.getQuantity()).replace(",",""));
            data.setTotalPrice(StringUtils.removeSpecialSymbol(data.getTotalPrice()).replace(",",""));
            data.setCartonNum(StringUtils.removeSpecialSymbol(data.getCartonNum()).replace(",",""));
            data.setNetWeight(StringUtils.removeSpecialSymbol(data.getNetWeight()).replace(",",""));
            data.setGrossWeight(StringUtils.removeSpecialSymbol(data.getGrossWeight()).replace(",",""));
            data.setCountryName(StringUtils.removeSpecialSymbol(data.getCountryName()));
            data.setGoodsCode(StringUtils.removeSpecialSymbol(data.getGoodsCode()));
            data.setSpec(StringUtils.removeSpecialSymbol(data.getSpec()));
        });
        List<ImportOrderMemberVO> imports = beanMapper.mapAsList(dataList,ImportOrderMemberVO.class);
        DecimalFormat format2 = new DecimalFormat("0.00");
        DecimalFormat format4 = new DecimalFormat("0.0000");
        imports.stream().forEach(importMember->{
            //数量和总价处理为2位小数点，毛重、净重保留4位小数
            if(StringUtils.isBigDecimal(importMember.getQuantity())) {
                importMember.setQuantity(importMember.getQuantity().contains(".") ? format2.format(new BigDecimal(importMember.getQuantity())) : importMember.getQuantity());
            } else {
                importMember.setQuantity(null);
            }
            if(StringUtils.isBigDecimal(importMember.getTotalPrice())) {
                importMember.setTotalPrice(importMember.getTotalPrice().contains(".") ? format2.format(new BigDecimal(importMember.getTotalPrice())) : importMember.getTotalPrice());
            } else {
                importMember.setTotalPrice(null);
            }
            if(StringUtils.isBigDecimal(importMember.getGrossWeight())) {
                importMember.setGrossWeight(importMember.getGrossWeight().contains(".") ? format4.format(new BigDecimal(importMember.getGrossWeight())) : importMember.getGrossWeight());
            } else {
                importMember.setGrossWeight("0.0000");
            }
            if(StringUtils.isBigDecimal(importMember.getNetWeight())) {
                importMember.setNetWeight(importMember.getNetWeight().contains(".") ? format4.format(new BigDecimal(importMember.getNetWeight())) : importMember.getNetWeight());
            } else {
                importMember.setNetWeight("0.0000");
            }
            //箱数
            if(!StringUtils.isInteger(importMember.getCartonNum())) {
                importMember.setCartonNum("0");
            }
            //单价后台处理
            if(StringUtils.isBigDecimal(importMember.getQuantity()) && StringUtils.isBigDecimal(importMember.getTotalPrice())) {
                BigDecimal quantity =  new BigDecimal(format2.format(new BigDecimal(importMember.getQuantity()))).multiply(new BigDecimal("100")).divide(new BigDecimal("100"));
                BigDecimal totalPrice = new BigDecimal(format2.format(new BigDecimal(importMember.getTotalPrice()))).multiply(new BigDecimal("100")).divide(new BigDecimal("100"));
                if(quantity.compareTo(BigDecimal.ZERO) == 1) {
                    importMember.setUnitPrice(totalPrice.divide(quantity,4,BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal("10000")).divide(new BigDecimal("10000")).toString());
                }
            } else {
                importMember.setUnitPrice("0.0000");
            }
        });
        stopwatch.stop();
        log.info("本次成功导入{}条数据，耗时：{}秒",dataList.size(),stopwatch.elapsed(TimeUnit.SECONDS));
        return imports;
    }

    @Override
    public Integer totalSingleQuantity(Date startDate, Date endDate) {
        endDate = DateUtils.parse(DateUtils.formatShort(endDate).concat(" 23:59:59"),"yyyy-MM-dd HH:mm:ss");
        return impOrderMapper.totalSingleQuantity(startDate,endDate);
    }

    @Override
    public BigDecimal totalAmountMoney(Date startDate, Date endDate) {
        endDate = DateUtils.parse(DateUtils.formatShort(endDate).concat(" 23:59:59"),"yyyy-MM-dd HH:mm:ss");
        return impOrderMapper.totalAmountMoney(startDate,endDate);
    }

    @Override
    public ImpOrderEntrustVO getPrintEntrustData(Long id) {
        ImpOrderDetailVO impOrder = impOrderMapper.detail(id);
        ValidatorUtils.isTrue(Objects.nonNull(impOrder),()->new ServiceException("订单不存在"));
        ImpOrderLogistics impOrderLogistics = impOrderLogisticsService.findByOrderId(id);
        ValidatorUtils.isTrue(Objects.nonNull(impOrderLogistics),()->new ServiceException("订单不存在"));
        Declaration declaration = declarationService.findByOrderId(id);
        ImpOrderEntrustVO impOrderEntrustVO = new ImpOrderEntrustVO();
        impOrderEntrustVO.setOrderNo(impOrder.getDocNo());
        impOrderEntrustVO.setOrderDate(impOrder.getOrderDate());
        impOrderEntrustVO.setCustomerName(impOrder.getCustomerName());
        impOrderEntrustVO.setSubjectName(impOrder.getSubjectName());
        impOrderEntrustVO.setSupplierName(impOrder.getSupplierName());
        ValidatorUtils.isTrueCall(Objects.nonNull(declaration),()->{
            impOrderEntrustVO.setIePortName(declaration.getIePortName());
        });
        impOrderEntrustVO.setCurrencyName(impOrder.getCurrencyName());
        impOrderEntrustVO.setDeliveryModeName(impOrderLogistics.getDeliveryModeName());
        impOrderEntrustVO.setTakeLinkPerson(impOrderLogistics.getTakeLinkPerson());
        impOrderEntrustVO.setTakeAddress(impOrderLogistics.getTakeAddress());
        impOrderEntrustVO.setTakeLinkTel(impOrderLogistics.getTakeLinkTel());
        impOrderEntrustVO.setReceivingModeName(impOrderLogistics.getReceivingModeName());
        impOrderEntrustVO.setSelfWareName(impOrderLogistics.getSelfWareName());
        impOrderEntrustVO.setSelfLinkPerson(impOrderLogistics.getSelfLinkPerson());
        impOrderEntrustVO.setSelfPersonId(impOrderLogistics.getSelfPersonId());
        impOrderEntrustVO.setSelfMemo(impOrderLogistics.getSelfMemo());
        impOrderEntrustVO.setMemo(impOrder.getMemo());

        List<ImpOrderMember> impOrderMembers = impOrderMemberService.getByOrderId(id);

        List<ImpOrderEntrustVO.InnerImpOrderMember> members = Lists.newArrayListWithExpectedSize(impOrderMembers.size());
        impOrderMembers.stream().forEach(member->{
            ImpOrderEntrustVO.InnerImpOrderMember innerMember = beanMapper.map(member,ImpOrderEntrustVO.InnerImpOrderMember.class);
            members.add(innerMember);
        });
        impOrderEntrustVO.setMembers(members);
        return impOrderEntrustVO;
    }

    @Override
    public Long exportEntrustExcel(Long id) {
        ImpOrderEntrustVO impOrderEntrustVO = getPrintEntrustData(id);
        String path = filePath + "temp/"+"scm"+"/order_entrust/";
        String sysFileName = StrUtil.format("{}-{}.xls",impOrderEntrustVO.getOrderNo(),System.currentTimeMillis());
        String fileName = StrUtil.format("委托进口货物确认单{}.xls",impOrderEntrustVO.getOrderNo());
        ValidatorUtils.isTrueCall(!new File(path).exists(),()->new File(path).mkdirs());
        WritableWorkbook wwb = null;
        try {
            wwb = jxl.Workbook.createWorkbook(new File(path + sysFileName));
            WritableSheet sheet1 = wwb.createSheet(impOrderEntrustVO.getOrderNo(), 0);
            WritableFont font18 = new WritableFont(WritableFont.ARIAL, 18, WritableFont.NO_BOLD, false);
            WritableFont font12 = new WritableFont(WritableFont.ARIAL, 10, WritableFont.NO_BOLD, false);
            WritableFont font12BOLD = new WritableFont(WritableFont.ARIAL, 10, WritableFont.BOLD, false);
            WritableCellFormat titleBold = new WritableCellFormat(font18);
            titleBold.setAlignment(Alignment.CENTRE);
            titleBold.setVerticalAlignment(VerticalAlignment.CENTRE);
            WritableCellFormat bold = new WritableCellFormat(font12);
            bold.setVerticalAlignment(VerticalAlignment.CENTRE);
            bold.setWrap(true);
            WritableCellFormat boldWrap = new WritableCellFormat(font12);
            boldWrap.setVerticalAlignment(VerticalAlignment.CENTRE);
            boldWrap.setWrap(true);
            WritableCellFormat cenBold = new WritableCellFormat(font12);
            cenBold.setAlignment(Alignment.CENTRE);
            cenBold.setVerticalAlignment(VerticalAlignment.CENTRE);
            WritableCellFormat boldBorder = new WritableCellFormat(font12);
            boldBorder.setBorder(jxl.format.Border.ALL, jxl.format.BorderLineStyle.THIN, jxl.format.Colour.BLACK);
            boldBorder.setWrap(false);
            boldBorder.setVerticalAlignment(VerticalAlignment.CENTRE);
            WritableCellFormat cenBoldBorder = new WritableCellFormat(font12BOLD);
            cenBoldBorder.setAlignment(Alignment.CENTRE);
            cenBoldBorder.setBorder(jxl.format.Border.ALL, jxl.format.BorderLineStyle.THIN, jxl.format.Colour.BLACK);
            cenBoldBorder.setWrap(true);
            cenBoldBorder.setVerticalAlignment(VerticalAlignment.CENTRE);
            Integer row = 0;
            sheet1.setColumnView(0, 5);
            sheet1.setColumnView(1, 14);
            sheet1.setColumnView(2, 15);
            sheet1.setColumnView(3, 17);
            sheet1.setColumnView(4, 9);
            sheet1.setColumnView(5, 9);
            sheet1.setColumnView(6, 9);
            sheet1.setColumnView(7, 9);
            sheet1.setColumnView(8, 10);
            sheet1.setColumnView(9, 9);
            sheet1.setColumnView(10, 9);
            sheet1.setColumnView(11, 9);
            sheet1.setColumnView(12, 9);

            sheet1.mergeCells(0, row, 12, row);
            sheet1.addCell(new Label(0, row++, "委托进口货物确认单", titleBold));
            sheet1.mergeCells(0, row, 12, row);
            sheet1.addCell(new Label(0, row++, "GOODS IMPORT CONFIRM FORM", titleBold));

            sheet1.mergeCells(0, row, 1, row);
            sheet1.mergeCells(2, row, 4, row);
            sheet1.mergeCells(6, row, 7, row);
            sheet1.mergeCells(8, row, 12, row);
            sheet1.addCell(new Label(0, row, "编号：", bold));
            sheet1.addCell(new Label(2, row, impOrderEntrustVO.getOrderNo(), bold));
            sheet1.addCell(new Label(6, row, "委托日期：", bold));
            sheet1.addCell(new Label(8, row++, LocalDateTimeUtils.formatTime(impOrderEntrustVO.getOrderDate(),"yyy-MM-dd"), bold));

            sheet1.mergeCells(0, row, 1, row);
            sheet1.mergeCells(2, row, 4, row);
            sheet1.mergeCells(6, row, 7, row);
            sheet1.mergeCells(8, row, 12, row);
            sheet1.addCell(new Label(0, row, "委托方：", bold));
            sheet1.addCell(new Label(2, row, impOrderEntrustVO.getCustomerName(), bold));
            sheet1.addCell(new Label(6, row, "代理方：", bold));
            sheet1.addCell(new Label(8, row++, impOrderEntrustVO.getSubjectName(), bold));

            sheet1.mergeCells(0, row, 1, row);
            sheet1.mergeCells(2, row, 4, row);
            sheet1.mergeCells(6, row, 7, row);
            sheet1.mergeCells(8, row, 12, row);
            sheet1.addCell(new Label(0, row, "供应商：", bold));
            sheet1.addCell(new Label(2, row, impOrderEntrustVO.getSupplierName(), bold));
            sheet1.addCell(new Label(6, row, "通关口岸：", bold));
            sheet1.addCell(new Label(8, row++, impOrderEntrustVO.getIePortName(), bold));
            row++;

            sheet1.addCell(new Label(0, row, "序号", cenBoldBorder));
            sheet1.addCell(new Label(1, row, "品名", cenBoldBorder));
            sheet1.addCell(new Label(2, row, "品牌", cenBoldBorder));
            sheet1.addCell(new Label(3, row, "型号", cenBoldBorder));
            sheet1.addCell(new Label(4, row, "产地", cenBoldBorder));
            sheet1.addCell(new Label(5, row, "数量", cenBoldBorder));
            sheet1.addCell(new Label(6, row, "单位", cenBoldBorder));
            sheet1.addCell(new Label(7, row, "委托单价", cenBoldBorder));
            sheet1.addCell(new Label(8, row, "委托总价", cenBoldBorder));
            sheet1.addCell(new Label(9, row, "币制", cenBoldBorder));
            sheet1.addCell(new Label(10, row, "净重KG", cenBoldBorder));
            sheet1.addCell(new Label(11, row, "毛重KG", cenBoldBorder));
            sheet1.addCell(new Label(12, row++, "箱数", cenBoldBorder));

            Integer ind = 1;
            BigDecimal t1 = BigDecimal.ZERO;
            BigDecimal t2 = BigDecimal.ZERO;
            BigDecimal t3 = BigDecimal.ZERO;
            BigDecimal t4 = BigDecimal.ZERO;
            Integer t5 = 0;

            String currencyName = impOrderEntrustVO.getCurrencyName();//币制名称
            for(ImpOrderEntrustVO.InnerImpOrderMember member : impOrderEntrustVO.getMembers()) {
                sheet1.addCell(new jxl.write.Number(0, row, ind++, boldBorder));
                sheet1.addCell(new Label(1, row, member.getName(), boldBorder));
                sheet1.addCell(new Label(2, row, member.getBrand(), boldBorder));
                sheet1.addCell(new Label(3, row, member.getModel(), boldBorder));
                sheet1.addCell(new Label(4, row, member.getCountryName(), boldBorder));
                sheet1.addCell(new Label(5, row, member.getQuantity().toString(), boldBorder));
                sheet1.addCell(new Label(6, row, member.getUnitName(), boldBorder));
                sheet1.addCell(new Label(7, row, member.getUnitPrice().toString(), boldBorder));
                sheet1.addCell(new Label(8, row, member.getTotalPrice().toString(), boldBorder));
                sheet1.addCell(new Label(9, row, currencyName, boldBorder));
                sheet1.addCell(new Label(10, row, member.getNetWeight().toString(), boldBorder));
                sheet1.addCell(new Label(11, row, member.getGrossWeight().toString(), boldBorder));
                sheet1.addCell(new jxl.write.Number(12, row++, member.getCartonNum(), boldBorder));
                t1 = t1.add(member.getQuantity()).setScale(2,BigDecimal.ROUND_HALF_UP);
                t2 = t2.add(member.getTotalPrice()).setScale(2,BigDecimal.ROUND_HALF_UP);
                t3 = t3.add(member.getNetWeight()).setScale(4,BigDecimal.ROUND_HALF_UP);
                t4 = t4.add(member.getGrossWeight()).setScale(4,BigDecimal.ROUND_HALF_UP);
                t5 += member.getCartonNum();
            }
            sheet1.mergeCells(0, row, 4, row);
            sheet1.addCell(new Label(0, row, "合计 Total：", boldBorder));
            sheet1.addCell(new Label(5, row, t1.toString(), boldBorder));
            sheet1.addCell(new Label(6, row, "", boldBorder));
            sheet1.addCell(new Label(7, row, "", boldBorder));
            sheet1.addCell(new Label(8, row, t2.toString(), boldBorder));
            sheet1.addCell(new Label(9, row, "", boldBorder));
            sheet1.addCell(new Label(10, row, t3.toString(), boldBorder));
            sheet1.addCell(new Label(11, row, t4.toString(), boldBorder));
            sheet1.addCell(new jxl.write.Number(12, row, t5, boldBorder));
            row++;
            row++;
            sheet1.mergeCells(0, row, 1, row);
            sheet1.addCell(new Label(0, row, "说明：", bold));
            row++;
            sheet1.mergeCells(1, row, 5, row);
            sheet1.addCell(new Label(1, row, "1) 请选择香港/境外/保税仓交货方式：", bold));
            sheet1.mergeCells(6, row, 12, row);
            sheet1.addCell(new Label(6, row, StrUtil.format("■ {}",impOrderEntrustVO.getDeliveryModeName()), bold));
            row++;
            sheet1.mergeCells(1, row, 5, row);
            sheet1.addCell(new Label(1, row, "   香港/境外详细提货地址（如需代理方代为提货）及联系人：", bold));
            sheet1.mergeCells(6, row, 12, row);
            sheet1.addCell(new Label(6, row, StrUtil.format("{} {} {}",impOrderEntrustVO.getTakeLinkPerson(),impOrderEntrustVO.getTakeLinkTel(),impOrderEntrustVO.getTakeAddress()), bold));
            row++;
            sheet1.mergeCells(1, row, 5, row);
            sheet1.addCell(new Label(1, row, "2) 请选择国内交货方式： ", bold));
            sheet1.mergeCells(6, row, 12, row);
            sheet1.addCell(new Label(6, row, StrUtil.format("■ {} {}",impOrderEntrustVO.getReceivingModeName(),StringUtils.null2EmptyWithTrim(impOrderEntrustVO.getLogisticsCompanyName())), bold));
            row++;
            sheet1.mergeCells(1, row, 12, row);
            sheet1.addCell(new Label(1, row, StrUtil.format("   提货信息：{} {} {} {}",StringUtils.null2EmptyWithTrim(impOrderEntrustVO.getSelfWareName()),StringUtils.null2EmptyWithTrim(impOrderEntrustVO.getSelfLinkPerson()),
                    impOrderEntrustVO.getSelfPersonId(),impOrderEntrustVO.getSelfMemo()), bold));
            row++;
            sheet1.mergeCells(1, row, 12, row);
            sheet1.addCell(new Label(1, row, StrUtil.format("3)客户特别要求（备注）：{}",StringUtils.null2EmptyWithTrim(impOrderEntrustVO.getMemo())), bold));
            row++;
            sheet1.mergeCells(7, row, 12, row);
            sheet1.addCell(new Label(7, row, "委托方签字并盖章确认：", bold));

            wwb.write();

            ExportFileDTO exportFileDTO = new ExportFileDTO();
            exportFileDTO.setPath(path+File.separator + sysFileName);
            exportFileDTO.setFileName(fileName);
            exportFileDTO.setOnce(Boolean.TRUE);
            exportFileDTO.setOperator("系统自动生成");

            Long fileId = exportFileService.save(exportFileDTO);
            return fileId;
        } catch (Exception e) {
            log.error("导出进口委托书异常",e);
            throw new ServiceException("导出进口委托书异常，请稍后再试");
        } finally {
            if(null != wwb) {
                try {
                    wwb.close();
                } catch (Exception e) {
                    log.error("关闭Workbook异常",e);
                }
            }
        }
    }

    @Override
    public BigDecimal summaryOrderAmount(ImpOrderQTO qto) {
        Map<String,Object> params = beanMapper.map(qto,Map.class);
        return impOrderMapper.summaryOrderAmount(params);
    }
}
